Почему const для неявного преобразования? - PullRequest
12 голосов
/ 09 октября 2010

После обширного прочтения ИСО / МЭК 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

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

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

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

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

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

Ответы [ 2 ]

14 голосов
/ 09 октября 2010

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

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

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

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

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

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

потому что это нормально, чтобы прикрепить константную ссылку к значению.

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

implicit_conversion_func(X(99));

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

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

int &ir = 3 + 2; // ERROR
const int &cir = 3 + 2; // OK
0 голосов
/ 09 октября 2010

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

...