C ++ неявные преобразования - PullRequest
23 голосов
/ 15 мая 2009

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

#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

Если вы можете указать, где я не прав, здесь или в оригинальном ответе, предпочтительно со ссылкой на Стандарт C ++, пожалуйста, сделайте это.

И ответ стандарта C ++ выглядит так:

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

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

Ответы [ 4 ]

12 голосов
/ 15 мая 2009

Я думаю, что ответ от sharptooth является точным. Раздел 12.3.4 стандарта C ++ (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 Не более одного пользовательского преобразования (конструктор или преобразование функция) неявно применяется к не замужем значение.

9 голосов
/ 15 мая 2009

Как кажется, консенсус уже есть: да, вы правы.

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

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

Пример: операторы сложения std :: string

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

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

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

8 голосов
/ 15 мая 2009

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

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

7 голосов
/ 15 мая 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...