Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual Studio fails to instantiate cast (conversion) operator template (T=bool) in the context of boolean operations

Why do Visual Studio 2010 and Visual Studio 2012 fail to compile this code?

Codepad.org, Xcode, gcc, LLVM, Clang all have no problem but Visual Studio poops the bed:

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;
}

Adding the explicit keyword doesn't change a thing for gcc or clang. The error message produced is:

error C2676: binary '||' : 'S' does not define this operator or a
  conversion to a type acceptable to the predefined operator
like image 467
Vinnie Falco Avatar asked Nov 17 '12 20:11

Vinnie Falco


1 Answers

It's a bug, at least in C++03 (not sure about C++11).

According to the overload resolution rules in C++03 §13.3.1.2, the built-in || operator is selected, since no user-defined || operator is defined for S.

§5.15/1 says:

The || operator groups left-to-right. The operands are both implicitly converted to bool (clause 4). [...]

§12.3/2 says:

User-defined conversions are applied only where they are unambiguous (10.2, 12.3.2). [...]

§12.3/5:

User-defined conversions are used implicitly only if they are unambiguous. [...] Function overload resolution (13.3.3) selects the best conversion function to perform the conversion.

§13.3.2/3:

Second, for F to be a viable function, there shall exist for each argument an implicit conversion sequence (13.3.3.1) that converts that argument to the corresponding parameter of F.

Clearly S defines a user-defined conversion to bool. The built-in || operator is a viable function for the overload resolution, and since it's the only one, it's the best. So the expression is well-formed.

Also of note is §4/3, which says:

An expression e can be implicitly converted to a type T if and only if the declaration “T t=e;” is well- formed, for some invented temporary variable t (8.5). [...]

So I'm curious whether Visual Studio also produces an error for the statement bool b = S();.

like image 59
Adam Rosenfield Avatar answered Sep 23 '22 11:09

Adam Rosenfield