与条件运算符一起使用时,动作不一致

decltype acting inconsistent when used in conjunction with conditional operator

本文关键字:不一致 条件运算符 一起      更新时间:2023-10-16

在研究c++ 11的一些新特性时,我注意到新的decltype关键字及其与条件操作符的交互有一些奇怪之处。

看到下面程序的输出,我非常惊讶:

#include <iostream>
#include <map>
int main(void)
{
    // set up a map that associates the internal compiler-defined type_info name with a human readable name
    std::map <std::string, std::string> types;
    types[typeid(decltype(static_cast<unsigned char  >(0))).name()] = "unsigned char";
    types[typeid(decltype(static_cast<unsigned short >(0))).name()] = "unsigned short";
    types[typeid(decltype(static_cast<short          >(0))).name()] = "short";
    types[typeid(decltype(static_cast<unsigned int   >(0))).name()] = "unsigned int";
    types[typeid(decltype(static_cast<int            >(0))).name()] = "int";
    types[typeid(decltype(static_cast<float          >(0))).name()] = "float";
    types[typeid(decltype(static_cast<double         >(0))).name()] = "double";
    types[typeid(decltype(static_cast<bool           >(0))).name()] = "bool";
    std::cout << "Should be unsigned char : " << types[typeid(decltype(static_cast<unsigned char >(0))).name()] << std::endl;
    std::cout << "Should be unsigned short: " << types[typeid(decltype(static_cast<unsigned short>(0))).name()] << std::endl;
    std::cout << "Should be short         : " << types[typeid(decltype(static_cast<short         >(0))).name()] << std::endl;
    std::cout << "Should be unsigned int  : " << types[typeid(decltype(static_cast<unsigned int  >(0))).name()] << std::endl;
    std::cout << "Should be int           : " << types[typeid(decltype(static_cast<int           >(0))).name()] << std::endl;
    std::cout << "Should be float         : " << types[typeid(decltype(static_cast<float         >(0))).name()] << std::endl;
    std::cout << "Should be double        : " << types[typeid(decltype(static_cast<double        >(0))).name()] << std::endl;
    std::cout << "Expecting unsigned short: " << types[typeid(decltype(
        false ? static_cast<unsigned char  >(0) :
        true  ? static_cast<unsigned short >(0) :
        false ? static_cast<         short >(0) :
        false ? static_cast<unsigned int   >(0) :
        false ? static_cast<         int   >(0) :
        false ? static_cast<         float >(0) :
        false ? static_cast<         double>(0) :
                static_cast<         bool  >(0)
        )).name()] << std::endl;
}

这导致了令人惊讶的输出:

Should be unsigned char : unsigned char
Should be unsigned short: unsigned short
Should be short         : short
Should be unsigned int  : unsigned int
Should be int           : int
Should be float         : float
Should be double        : double
Expecting unsigned short: double
我希望看到如下输出(注意最后一行):
Should be unsigned char : unsigned char
Should be unsigned short: unsigned short
Should be short         : short
Should be unsigned int  : unsigned int
Should be int           : int
Should be float         : float
Should be double        : double
Expecting unsigned short: unsigned short

有人知道为什么会发生这种情况吗?

你需要改变你的期望。条件表达式的类型仅取决于其操作数的类型,而不取决于操作数的值。

有许多规则用于根据第二个和第三个操作数的类型确定条件表达式的公共类型。第二个和第三个操作数的值,即使是常量表达式,也不会被考虑。

您应该查阅标准以了解确定通用类型的规则的详细信息。如果找不到通用类型,程序通常是病态的。

三元表达式的结果类型与最后两个参数的类型相同。在c++ 11中,有一个std::common_type trait可以获得该类型(如果我没记错的话,它实际上是作为decltype( false ? x : y )实现的)。

您在最后一个表达式中得到的是bool, int, short, double等常见的类型…

条件表达式的结果类型是最后两个参数的类型。最后两个参数需要是相同的类型。在您的示例中,所有内容都被提升为两倍以满足此要求。如果在表达式中添加了不能隐式强制为double的类型(例如void*),将会出现编译错误。

在这种情况下,Decltype是一种转移注意力的方法。此行为继承自c。