C++ decltype与条件运算符一起使用时不一致
在研究一些新的C++11特性时,我观察到与新的decltype关键字及其与条件运算符的交互有关的一些奇怪之处 我非常惊讶地看到以下程序的输出:C++ decltype与条件运算符一起使用时不一致,c++,c++11,decltype,C++,C++11,Decltype,在研究一些新的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 s
#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;
}
我希望看到以下输出(注意最后一行):
有人知道为什么会这样吗?我使用的是GNU g++。条件表达式的结果类型是最后两个参数的类型。最后两个参数的类型必须相同。在您的示例中,为了满足此要求,所有内容都被提升为double。如果向表达式中添加不能隐式强制为double的类型(例如void*),则会出现编译器错误
在这种情况下,Decltype是一种转移注意力的手段。这种行为是从C继承而来的。您需要改变您的期望。条件表达式的类型仅取决于其操作数的类型,而不取决于其操作数的值 有许多规则用于根据第二个和第三个操作数的类型确定条件表达式的公共类型。不考虑第二个和第三个操作数的值,即使它们是常量表达式
有关确定通用类型的规则的详细信息,请参考标准。如果找不到公共类型,则程序通常格式不正确。三元表达式的结果类型是最后两个参数的公共类型。在C++11中,有一个
std::common_type
特性可以得到该类型(如果我没记错的话,它实际上被实现为decltype(false?x:y)
)
您在上一个表达式中得到的是一种常见于
bool
、int
、short
、double
,等等的类型。没有合适的编译器来检查它,但下面的方法对我来说很好:`std::cout必须将其分解为两个注释。“我有gcc版本4.5.2(gcc)最后一个操作数到?:
不必具有相同的类型,在许多情况下,它们可以具有不同的类型,但其中一个可以转换为另一个的类型(或第三个公共类型)。操作数的提升/强制是在计算表达式之前还是之后发生的?我以前会这样想,因此我认为我所说的在技术上仍然是正确的,尽管可能会产生误导。目标类型在编译时是固定的,因为它只取决于操作数的类型。提升/强制只能在对表达式求值时发生。只允许计算第二个或第三个参数中的一个,因此我不太确定您的评论是什么意思。相关(FDIS)标准见§5.16/3(条件运算符)和§5/9(常用算术转换)。有关迂腐的细节,请参阅Eric Niebler的优秀文章。
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