8

After reading this I tried making such conversion with static_cast:

class A;

class B { 
      public: 
         B(){} 

         B(const A&) //conversion constructor
         { 
              cout << "called B's conversion constructor" << endl; 
         } 
};

class A { 
      public: 
         operator B() const //conversion operator
         { 
              cout << "called A's conversion operator" << endl; 
              return B(); 
         } 
};

int main()
{
    A a;

    //Original code, This is ambiguous, 
    //because both operator and constructor have same cv qualification (use -pedantic flag)
    B b = a;

    //Why isn't this ambiguous, Why is conversion constructor called, 
    //if both constructor and  operator have same c-v qualification
    B c = static_cast<B>(a); 
    return 0;
}

I expected it to not compile, because both constructor and operator have same c-v qualification. However it compiled, successfully and static_cast calls constructor instead of operator. Why?

(compiled using gcc 4.8.1 with pedantic and Wall flags)

Community
  • 1
  • 1
PcAF
  • 1,975
  • 12
  • 20

1 Answers1

8

The C++11 Standard says (emphasis mine):

5.2.9 Static cast

4 Otherwise, an expression e can be explicitly converted to a type T using a static_cast of the form static_cast<T>(e) if the declaration T t(e); is well-formed, for some invented temporary variable t (8.5). The effect of such an explicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion. The expression e is used as a glvalue if and only if the initialization uses it as a glvalue.

5 Otherwise, the static_cast shall perform one of the conversions listed below. No other conversion shall be performed explicitly using a static_cast.

That explains why the static_cast in

B c = static_cast<B>(a); 

ends up calling the constructor of B.

The conversion operator is used only if the T t(e) is not well-formed.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • I understand that this sentence means that if `B temporary(a)` is valid `static_cast` can be preformed, but I don't see there why constructor takes precedence. – PcAF May 03 '16 at 20:33
  • @PcAF, I couldn't find a clause that says the `static_cast` can be performed using the conversion operator. However, if there is one, it is given lower precedence than the above. – R Sahu May 03 '16 at 20:35
  • @R Sahu Remove `B(const A&)` conversion constructor and now `static_cast` works with conversion operator. – PcAF May 03 '16 at 20:39
  • @PcAF, the conversion operator is given lower precedence. See the updated answer. – R Sahu May 03 '16 at 20:42
  • @R Sahu Your answer makes sense and is correct. And do you have reference in standard for that? Because in sentence you highlighted I don't see anything about precedence. – PcAF May 03 '16 at 20:59
  • @PcAF, the "Otherwise" in the start of the clauses implies precedence. – R Sahu May 03 '16 at 21:01