Подтвердить что ты не робот

Visual Studio не создает экземпляр шаблона оператора преобразования (преобразования) (T = bool) в контексте логических операций

Почему 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
4b9b3361

Ответ 1

Это ошибка, по крайней мере, в С++ 03 (не уверен о С++ 11).

В соответствии с правилами разрешения перегрузки в С++ 03 §13.3.1.2 выбирается встроенный оператор ||, поскольку для S не определен пользовательский || -оператор.

В §5.15/1 говорится:

Операторы группы || слева направо. Операнды оба неявно преобразуются в bool (раздел 4). [...]

В §12.3/2 говорится:

Пользовательские преобразования применяются только там, где они недвусмысленны (10.2, 12.3.2). [...]

§12.3/5:

Пользовательские преобразования используются неявно, только если они недвусмысленны. [...] Функция перегрузки разрешения (13.3.3) выбирает лучшую функцию преобразования для выполнения преобразования.

§13.3.2/3:

Во-вторых, для F, чтобы быть жизнеспособной функцией, для каждого аргумента будет существовать неявная последовательность преобразований (13.3.3.1), которая преобразует этот аргумент в соответствующий параметр F.

Ясно, что S определяет пользовательское преобразование в bool. Встроенный оператор || является жизнеспособной функцией для разрешения перегрузки, и поскольку он единственный, он лучший. Таким образом, выражение хорошо сформировано.

Также следует отметить §4/3, в котором говорится:

Выражение e может быть неявно преобразовано в тип T тогда и только тогда, когда декларация "T t=e;" корректна для некоторой изобретенной временной переменной T (8.5). [...]

Итак, мне любопытно, создает ли Visual Studio ошибку для оператора bool b = S();.

Ответ 2

Если вы форбируете неявное приведение типов в boolean, компилятор должен проверить, существует ли оператор || определенный, который принимает логическое значение. Это (надеюсь,!) Не определено, потому что это нарушит ярлыки. Поэтому он должен проверить, есть ли определенный оператор преобразования, который дает ему что-то определенное для глобального || -оператора. Не могли бы вы решить эту проблему, добавив оператор преобразования в bool, BOOL или int (все равно это все равно ^^)...?

operator bool() {return this != null && this != 0xcccccccc;}

Это BTW было бы просто взломом, было бы лучше обеспечить логически значимое преобразование.

Im shure существует константа, определенная для отметки 0xcccccccc для неинициализированной памяти в режиме отладки, но я ее не знаю.