Почему 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 не отвечали на мой вопрос.
- Может кто-то пролить свет на то, что эффект
const
имеет на неявные преобразования? - Использует ли использование
const
преобразование "однозначно" по 12,3 строке 2? -
const
ли const
либо эффект lvalue vs. rvalue, о котором говорится в разделе 4?
Ответы
Ответ 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
.