Почему оператор преобразования не вызывается при использовании синтаксиса инициализации, и почему сообщение об ошибке clang кажется неправильным?

У меня есть следующий код, который создает один объект t2 с помощью явного конструктора преобразования, который выполняет неявное преобразование t1. Это ожидается и описано в языке программирования C ++, в разделе 11.4.1 третьего издания.

#include <iostream>
#include <string>
using namespace std;

class test1 {
public:
test1() {}
operator string() {
cout << "test1 string conversion operator called" << endl;
return string();
}
};
class test2 {
public:
test2() {}
test2(string s) {
cout << "test2 string conversion constructor called" << endl;
}
};

int main() {
test1 t1;
test2 t2(t1);
return 0;
}

И, как и следовало ожидать:

> clang++ --version
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.2
Thread model: posix
> clang++ -std=c++11 test.cc
> ./a.out
test1 string conversion operator called
test2 string conversion constructor called

Однако при изменении конструкции t2 на синтаксис инициализации:

test1 t1;
test2 t2 = t1;
return 0;

Clang выводит следующее:

test.cc:23:15: error: no viable conversion from 'test1' to 'test2'
test2 t2 = t1;
^    ~~
test.cc:13:11: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'test1' to 'const test2 &' for 1st argument
class test2 {
^
test.cc:13:11: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'test1' to 'test2 &&' for 1st argument
class test2 {
^
test.cc:16:9: note: candidate constructor not viable: no known conversion from 'test1' to 'string' (aka 'basic_string<char, char_traits<char>, allocator<char> >') for 1st argument
test2(string s) {
^
test.cc:8:9: note: candidate function
operator string() {
^
1 error generated.

Я не знаю, должна ли инициализация выполнять неявное преобразование, подобное этому, но сообщение об ошибке кажется очень-очень неправильным. нет известного преобразования из ‘test1’ в ‘string’, все же это даже показывает оператор-кандидат функция string () {

Что дает? И что стандарт C ++ говорит о неявных преобразованиях в конструкторах инициализации? я предполагать что это должно учитываться как два неявных преобразования и, следовательно, не допускается, но вывод компилятора вовсе не предполагает этого.

3

Решение

Во-первых, неправильно звонить test2::test2(string) «конструктор явного преобразования». Он будет использоваться в неявных преобразованиях (отметьте его explicit если ты не хочешь этого).

Во всяком случае, сообщение об ошибке Clang на месте, и он почти идеально объясняет, что происходит.
Это:

test2 t2(t1);

называется прямая инициализация. Все конструкторы для test2 являются кандидатами и, кроме того, компилятор может запустить последовательность неявных преобразований в соответствии с аргументами. Находит test1::operator string а также test2::test(string) и все хорошо.

Это:

test2 t2 = t1;

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

4

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector