为什么Visual Studio 2010和Visual Studio 2012无法编译此代码?
Codepad.org,Xcode,gcc,LLVM,Clang都没有问题但是Visual Studio却在床上大踏步走:
struct S {
template <class T> inline operator T () const { return T (); }
};
int main () {
// NOTE: "S()" denotes construction in these examples
struct F {
void operator() (bool) { }
static void toint (int) { }
static void tostr (char const*) { }
};
bool b1 = S (); // Okay
bool b2 (S ()); // Okay
F () (S ()); // Okay
F::toint (S ());// Okay
F::tostr (S ());// Okay
S () || false; // Error: error C2676: binary '||' : 'vf::S' does
// not define this operator or a conversion to a type
// acceptable to the predefined operator
return 0;
}
添加explicit
关键字不会改变gcc或clang的内容。产生的错误消息是:
error C2676: binary '||' : 'S' does not define this operator or a
conversion to a type acceptable to the predefined operator
答案 0 :(得分:3)
这是一个错误,至少在C ++ 03中(不确定C ++ 11)。
根据C ++03§13.3.1.2中的重载决策规则,选择了内置||
运算符,因为没有为{{1}定义用户定义的||
运算符}。
§5.15/ 1说:
S
运算符组从左到右。操作数都隐式转换为||
(第4节)。 [...]
§12.3/ 2说:
用户定义的转换仅在明确无误的情况下应用(10.2,12.3.2)。 [...]
§12.3/ 5:
只有在明确无误的情况下,才会隐式使用用户定义的转换。 [...]函数重载决策(13.3.3)选择最佳转换函数来执行转换。
§13.3.2/ 3:
其次,要使
bool
成为可行的函数,每个参数都应存在一个隐式转换序列(13.3.3.1),它将该参数转换为F
的相应参数。
显然F
定义了用户定义的S
转换。内置的bool
运算符是重载决策的可行函数,因为它是唯一的运算符,所以它是最好的。所以表达形式很好。
同样值得注意的是§4/ 3,其中说:
当且仅当声明“
||
”格式正确时,表达式e
可以隐式转换为类型T
,对于某些发明的临时变量T t=e;
(8.5)。 [...]
所以我很好奇Visual Studio是否也为语句t
生成错误。
答案 1 :(得分:0)
如果你将隐式类型转换为布尔值,编译器必须检查是否有运算符||定义哪个采用布尔值。这是(希望!)没有定义,因为它会打破捷径。所以他必须检查是否有一个转换运算符定义为它提供了为全局|| -operator定义的东西。你可以通过向bool,BOOL或int添加转换运算符来解决这个问题(无论如何都是^^)......?
operator bool() {return this != null && this != 0xcccccccc;}
这个BTW只是一个黑客,提供一个逻辑上有意义的转换会更好。
我确实在调试模式下有一个为0xcccccccc标记未初始化内存的常量,但我不知道。