-std:C++17 /Zc:ternary
选项的MSVC不能编译。struct CStringPtr
{
const char *m_pString = nullptr;
CStringPtr() = default;
CStringPtr( const char *pString ) : m_pString( pString ) { }
operator const char *() const { return m_pString; }
};
int main( int argc, char ** )
{
bool b = !!argc;
const char *X = b ? CStringPtr( "inside" ) : "naked";
const char *Y = b ? "naked" : CStringPtr( "inside" );
CStringPtr Z = b ? CStringPtr( "inside" ) : "naked";
CStringPtr W = b ? "naked" : CStringPtr( "inside" );
// Silence unused-variable warnings.
return X && Y && Z && W;
}
带有三种编译器的godbolt编译器探索链接: https://godbolt.org/z/6d5Mrjnd7
MSVC针对这四行代码中的每一行都会发出错误:
<source>(19): error C2445: result type of conditional expression is ambiguous: types 'const char [6]' and 'CStringPtr' can be converted to multiple common types
<source>(19): note: could be 'const char *'
<source>(19): note: or 'CStringPtr'
相反,对于所有这四种情况,Clang/GCC都为裸字符串调用CStringPtr构造函数。
在MSVC /Zc:ternary文档中,他们声称该标志可以启用符合标准的三元运算符解析,这意味着MSVC的实现存在错误或者Clang/GCC在此处不符合标准要求。
还有一个需要注意的地方是,在这种具体情况下,MSVC文档提到了与使用const char *
类型相关的异常:
重要的例外是当操作数的类型为其中之一的以空字符结尾的字符串类型(例如const char*、const char16_t*等)时。您也可以使用数组类型及其衰减的指针类型来复制效果。当实际的第二个或第三个操作数为相应类型的字符串字面值时,其行为取决于所使用的语言标准。C++17从C++14中更改了此案例的语义。
那么,MSVC在C++17规则下是否不符合标准?还是Clang/GCC不符合标准?