static_cast Конструктор преобразования против оператора преобразования

Прочитав это, я попытался выполнить такое преобразование с помощью 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;
}

Я ожидал, что он не будет компилироваться, потому что и конструктор, и оператор имеют одинаковую квалификацию c-v. Однако он успешно скомпилирован и static_cast вызывает конструктор вместо оператора. Почему?

(скомпилировано с использованием gcc 4.8.1 с флагами pedantic и Wall)


person PcAF    schedule 03.05.2016    source источник


Ответы (1)


Стандарт C ++ 11 говорит (выделено мной):

5.2.9 Статическая трансляция

4 В противном случае выражение e может быть явно преобразовано в тип T с использованием static_cast формы static_cast<T>(e) , если объявление T t(e); правильно сформировано для некоторой придуманной временной переменной t (8.5). Эффект от такого явного преобразования такой же, как при выполнении объявления и инициализации с последующим использованием временной переменной в качестве результата преобразования. Выражение e используется как glvalue тогда и только тогда, когда инициализация использует его как glvalue.

5 В противном случае static_cast должен выполнить одно из преобразований, перечисленных ниже. Никакое другое преобразование не должно выполняться явно с использованием static_cast.

Это объясняет, почему static_cast в

B c = static_cast<B>(a); 

заканчивается вызовом конструктора B.

Оператор преобразования используется только в том случае, если T t(e) имеет неправильный формат.

person R Sahu    schedule 03.05.2016
comment
Я понимаю, что это предложение означает, что если B temporary(a) действительно, static_cast может быть предварительно сформировано, но я не понимаю, почему конструктор имеет приоритет. - person PcAF; 03.05.2016
comment
@PcAF, мне не удалось найти предложение, в котором говорится, что static_cast можно выполнить с помощью оператора преобразования. Однако, если он есть, ему дается более низкий приоритет, чем вышеупомянутый. - person R Sahu; 03.05.2016
comment
@R Sahu Удалите B(const A&) конструктор преобразования, и теперь static_cast работает с оператором преобразования. - person PcAF; 03.05.2016
comment
@PcAF, оператору преобразования дается более низкий приоритет. См. Обновленный ответ. - person R Sahu; 03.05.2016
comment
@R Sahu Ваш ответ имеет смысл и правильный. И есть ли у вас ссылка в стандарте на это? Поскольку в предложении, которое вы выделили, я ничего не вижу о приоритете. - person PcAF; 03.05.2016
comment
@PcAF, Иначе в начале предложений подразумевает приоритет. - person R Sahu; 04.05.2016