【发布时间】:2021-08-22 20:40:50
【问题描述】:
以下代码在 C++17 标准下的 Clang/GCC 下编译,但在带有 -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 documentation 中,他们声称该标志启用了三元运算符的符合标准的解析,这意味着 MSVC 的实现中存在错误或 Clang/GCC 在此处不符合标准。
这里的另一个注意事项是,MSVC 文档在这种确切的情况下提到了一个关于正在使用的 const char * 类型的异常:
这种常见模式的一个重要例外是当操作数的类型是空终止字符串类型之一时,例如 const char*、const char16_t* 等。您还可以使用数组类型和它们衰减到的指针类型来重现效果。 ?: 的实际第二个或第三个操作数是相应类型的字符串文字时的行为取决于所使用的语言标准。 C++17 已从 C++14 更改了此案例的语义。
那么,MSVC 不符合 C++17 规则吗?还是 Clang/GCC?
【问题讨论】:
标签: c++ visual-c++ c++17 language-lawyer