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

Неявные преобразования С++

Несколько комментариев по моему недавнему ответу, Какие другие полезные приведения могут быть использованы в С++, свидетельствуют о том, что мое понимание конверсий на С++ ошибочно. Чтобы прояснить эту проблему, рассмотрите следующий код:

#include <string>

struct A {
    A( const std::string & s ) {}
};

void func( const A & a ) {
}

int main() {
    func( "one" );                  // error
    func( A("two") );           // ok
    func( std::string("three") );   // ok
}

Мое утверждение состояло в том, что первый вызов функции является ошибкой, потому что нет никакого преобразования из const char * в A. Существует преобразование из строки в A, но использование этого будет включать в себя больше, чем один конвертация. Я понимаю, что это недопустимо, и это, похоже, подтверждается компиляторами g++ 4.4.0 и Comeau. С Comeau я получаю следующую ошибку:

"ComeauTest.c", line 11: error: no suitable constructor exists 
      to convert from "const char [4]" to "A"
      func( "one" );                    // error

Если вы можете указать, где я ошибаюсь, либо здесь, либо в исходном ответе, желательно со ссылкой на стандарт С++, сделайте это.

И ответ со стандартом С++ выглядит следующим образом:

Не более одного пользовательского преобразования (функция конструктора или преобразования) неявно применяется к одному значению.

Спасибо Абхай за предоставление цитаты.

4b9b3361

Ответ 1

Я думаю, что ответ от sharptooth является точным. Раздел 12.3.4 С++ Standard (SC22-N-4411.pdf) под названием "Конверсии" дает понять, что допускается только одно неявное пользовательское преобразование.

1 Тип преобразования объектов класса может быть задан конструкторы и конверсия функции. Эти     конверсии называются пользовательскими преобразованиями и используются для неявных преобразований типов (пункт 4), для     инициализация (8.5) и для явного преобразования типов (5.4, 5.2.9).

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

3 [Примечание: см. 13.3 для обсуждения использования конверсий в вызовах функций, а также в примерах ниже. -конец     примечание]

4 Не более одного определяемого пользователем преобразования (конструктор или преобразование функция) неявно применяется к Один     значение.

Ответ 2

Поскольку консенсус, похоже, уже есть: да, вы правы.

Но поскольку этот вопрос/ответы, вероятно, станет точкой отсчета для неявных преобразований С++ в stackoverflow, я бы хотел добавить, что для аргументов шаблона правила разные.

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

Случай в точке, std::string операторы сложения

 std::string s;
 s += 67;    // (1)
 s = s + 67; // (2)

(1) компилируется и работает нормально, operator+= является функцией-членом, шаблонный параметр шаблона уже выводится путем создания экземпляра std::string для s (до char). Таким образом, допускаются неявные преобразования (intchar), приводит к s, содержащему эквивалент char, равный 67, например. в ASCII это станет "C"

(2) дает ошибку компилятора, поскольку operator+ объявляется как свободная функция, и здесь аргумент символа шаблона используется в выводе.

Ответ 3

Это правда, допускается только одно неявное преобразование.

Два преобразования в строке могут выполняться с комбинацией оператора преобразования и параметризованного конструктора, но это вызывает предупреждение C4927 - "незаконный преобразование, недвусмысленно применяется более одного пользовательского преобразования" - в VС++ по какой-либо причине.

Ответ 4

Язык программирования С++ (4-е изд.) (раздел 18.4.3) гласит, что

только один уровень пользовательских неявное преобразование является законным

Эта "определяемая пользователем" часть делает ее похожей на несколько неявных преобразований, если некоторые из них находятся между нативными типами.