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

Почему const для неявного преобразования?

После обширного чтения ISO/IEC 14882, язык программирования - C++, я все еще не уверен, почему const необходим для неявного преобразования в пользовательский тип с помощью одного конструктора аргументов, такого как следующий

#include <iostream>

class X {
public:
   X( int value ) {
      printf("constructor initialized with %i",value);
   }
}

void implicit_conversion_func( const X& value ) {
   //produces "constructor initialized with 99"
}

int main (int argc, char * const argv[]) {
   implicit_conversion_func(99);
}



Начиная с раздела 4, строка 3

Выражение e может быть неявно преобразовано в тип T тогда и только тогда, когда объявление T t = e; хорошо сформирована, для некоторой изобретенной временной переменной t (8.5). Для некоторых языковых конструкций требуется, чтобы выражение было преобразовано в логическое значение. Выражение e, отображаемое в таком контексте, называется контекстно преобразованным в bool и хорошо сформировано тогда и только тогда, когда декларация bool t (e); хорошо сформирована, для некоторой изобретенной временной переменной t (8.5). Эффект либо неявного преобразования является таким же, как выполнение объявления и инициализации, а затем использование временной переменной в результате преобразования. Результатом является lvalue, если T - ссылочный тип lvalue (8.3.2) и rvalue в противном случае. Выражение e используется как lvalue тогда и только тогда, когда инициализация использует его как lvalue.

После этого я нашел раздел инициализаторов, относящихся к пользовательским типам в 8.5 строке 6

Если программа вызывает инициализацию по умолчанию объекта с типом const, T, то T должен быть типом класса с предоставленным пользователем конструктором по умолчанию.

Наконец, я оказался в 12.3 строке 2 о пользовательских преобразованиях, в которых говорится:

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

Излишне говорить, что 10.2 и 12.3.2 не отвечали на мой вопрос.

  1. Может кто-то пролить свет на то, что эффект const имеет на неявные преобразования?
  2. Использует ли использование const преобразование "однозначно" по 12,3 строке 2?
  3. const ли const либо эффект lvalue vs. rvalue, о котором говорится в разделе 4?
4b9b3361

Ответ 1

Это не имеет особого отношения к тому, что преобразование неявно. Более того, это не имеет особого отношения к конверсиям. Это действительно значение rvalues ​​против lvalues.

Когда вы конвертируете 99 в тип X, результатом является rvalue. В С++ результаты преобразований всегда rvalues ​​(если вы не конвертируете в ссылочный тип). В С++ запрещено использовать неконстантные ссылки на rvalues.

Например, этот код не будет компилировать

X& r = X(99); // ERROR

потому что он пытается привязать не-const ссылку на rvalue. С другой стороны, этот код хорош

const X& cr = X(99); // OK

потому что вполне нормально присоединять ссылку const к rvalue.

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

implicit_conversion_func(X(99));

и в итоге получится такая же ситуация: с const он компилируется, без const это не так.

Опять же, единственная роль, которую играет конверсия (явная или неявная), заключается в том, что она помогает нам генерировать rvalue. В общем, вы можете произвести rvalue каким-то другим способом и столкнуться с тем же вопросом

int &ir = 3 + 2; // ERROR
const int &cir = 3 + 2; // OK

Ответ 2

В разделе 5.2.2 параграфа 5, когда аргумент функции имеет тип ссылки const, при необходимости автоматически вводится временная переменная. В вашем примере результат rvalue X(99) должен быть помещен во временную переменную, чтобы эта переменная могла быть передана с помощью const ссылки на implicit_conversion_func.