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

если программа вызывает инициализацию по умолчанию объекта типа T, отвечающего требованиям const, 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 ответов


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

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

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

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

потому что он пытается прикрепить ссылку non-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

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