【问题标题】:What's the purpose of std::to_integer?std::to_integer 的目的是什么?
【发布时间】:2019-06-22 22:10:31
【问题描述】:

据我所知,std::to_integer<T> 等价于T(value),其中value 是一个类型为std::byte 的变量。
我查看了主要编译器的一些实现,发现在这种情况下,equivalent 的字面意思是 implemented as。换句话说,大多数时候to_integer实际上是这样实现的:

return T(value);

仅此而已。

我不明白这样一个功能的目的是什么?
具有讽刺意味的是,缺点甚至超过了优点。我应该为这样的函数包含一个完整的标头,以避免最有可能直接内联的类 C 类型转换。

还有其他原因吗,或者它只是一个漂亮的类 C 演员的替代品,仅此而已?

【问题讨论】:

  • 标题的抱怨是不公平的。如果您使用std::byte,则该标头已经包含(或者更好!)
  • std::to_integer<T>constexprT(value) 不一定相同。
  • @SilvanoCerza 它实际上是作为一个返回T(value) 的constexpr 函数实现的。和T(value)有什么区别?我不明白,但这听起来很有趣,如果可能的话,我邀请您在答案中更好地表述这一点。谢谢。
  • 我认为这可能与 ADL 有关,但我不确定。

标签: c++ c++17 c++-standard-library


【解决方案1】:

对于类似 C 的演员表来说,它真的是一个好看的替代品,仅此而已?

你这么说好像是一些琐碎的细节。

演员表很危险。将某些内容转换为错误的类型很容易,而且编译器通常不会阻止您这样做。此外,由于std::byte 不是 C++ 中的整数类型,因此处理数字字节值通常需要大量转换。具有显式转换为整数的函数可提供更安全的用户体验。

例如,float(some_byte) 是完全合法的,而 to_integer<float>(some_byte) 是明确禁止的。 to_integer<T> 要求 T 是一个整数类型。

to_integer 是一个更安全的替代方案。

我应该为这样的函数包含一个完整的标题

如果通过“整个标题”,您的意思是 相同的标题您从 std::byte 获得,因此根据定义已经包含...

【讨论】:

    【解决方案2】:

    std::to_integer<T>(some_byte) 等价于T(some_byte) 如果它实际编译T(some_byte) 相当于 (T)some_byte 的不安全 C 风格转换,可以 do scary things。另一方面,std::to_integer 被适当地限制为仅在安全时工作:

    仅当std::is_integral_v<IntegerType> 为真时,此重载才参与重载决议。

    如果T 实际上不是整数类型,而不是可能具有未定义的行为,则代码将无法编译。如果some_byte 实际上不是std::byte,而不是可能具有未定义的行为,则代码将无法编译。

    【讨论】:

    • 您有没有从强制转换到整数类型的未定义行为示例(特别是从非指针类型,可能实现可以选择未定义行为)?
    • @DavisHerring 我非常谨慎地选择了“可能具有未定义行为”这个短语。如果您执行不正确的转换并使用该转换的结果,您将有未定义的行为。例如,如果T 实际上是一个指针,如果some_byte 实际上是一个指针,如果其中一个是引用(我必须仔细考虑规则才能知道引用何时正确)。关键是 C 风格转换的接口可以让你做危险和不安全的事情,但 std::to_integer 不会。
    • @DavisHerring 另外,实现不能“选择未定义的行为”;这不取决于实施。该标准选择是否定义某些行为。实现不能选择使某些行为未定义。他们可以选择定义未定义的行为,但不能取消定义已定义的行为。
    • 表达式永远不会有引用类型,只有当它调用函数时,转换为非引用类型才与源的值类别有关。至于“实现定义的未定义行为”,我说“可能”的原因与您说的“可能”大致相同——实现可以合理地说将整数转换为指针涉及读取(可能无效的)指针左右.
    【解决方案3】:

    除了已经提到的意图和安全问题的表达之外,我从委员会对论文的讨论中了解到,它应该类似于 std::to_string,并且将来可能会有更多的过载。

    【讨论】:

    • 这是一个很好的观点。可以通过引用委员会的一些讨论并解释讨论如何暗示这一点来改进它,但未来的演变是std::to_integer 的一个原因是有道理的。
    • @Justin:确切的会议纪要不会公布,但无论如何也没什么可引用的(除了与to_string 的比较之外)——因此“我明白了”。我认为还有可能仍在考虑不支持static_cast<int>(myByte) 的替代设计。
    【解决方案4】:

    C 样式转换不等同于std::to_integer<T>。请参见下面的示例。

    std::to_integer<T> 仅在std::is_integral_v<T> 为真时才参与重载决议。

    #include <cstddef>
    #include <iostream>
    
    template <typename T>
    auto only_return_int_type_foo(std::byte& b)
    {
        return std::to_integer<T>(b);
    }
    
    template <typename T>
    auto only_return_int_type_bar(std::byte& b)
    {
        return T(b);
    }
    
    int main()
    {
        std::byte test{64};
        // compiles
        std::cout << only_return_int_type_foo<int>(test) << std::endl;
    
        // compiler error
        std::cout << only_return_int_type_foo<float>(test) << std::endl;
    
        // compiles
        std::cout << only_return_int_type_bar<int>(test) << std::endl;
    
        // compiles
        std::cout << only_return_int_type_bar<float>(test) << std::endl;
    } 
    

    【讨论】:

      猜你喜欢
      • 2014-04-04
      • 2011-09-24
      • 1970-01-01
      • 1970-01-01
      • 2013-03-20
      • 1970-01-01
      • 1970-01-01
      • 2015-01-20
      • 2020-03-19
      相关资源
      最近更新 更多