Создание значения с помощью двух неявных конструкторов?

TLDR: У меня есть два шаблонных класса Outer а также Inner, Inner<X> может быть неявно построен из X, а также Outer<Y> может быть неявно построен из Y, Должен Outer<Inner<X>> = X() Работа?

Больше деталей:

Предположим, у меня есть следующие два класса:

template<typename T>
class Inner {
public:
Inner(const T& value) {}
Inner(T&& value) {}
};

template<typename T>
class Outer {
public:
Outer(const T& value) {}
Outer(T&& value) {}
};

Рассмотрим следующую функцию:

struct SomeType{};
Outer<Inner<SomeType>> DoSomethingFails() {
SomeType value;
return value;
}

G ++ жалуется:

no viable conversion from 'SomeType' to 'Outer<Inner<SomeType> >'
note: candidate constructor not viable: no known conversion from 'SomeType' to 'const Inner<SomeType> &' for 1st argument

Но если я сделаю следующее вместо этого:

Outer<Inner<SomeType>> DoSomethingWorks() {
SomeType value;
return Inner<SomeType>(value);
}

Оно работает. Разумно ли ожидать DoSomethingFails работать? Если нет, то почему? И может ли код быть изменен таким образом, чтобы DoSomethingFails работает?

3

Решение

Ваш первый пример требует двух пользовательских преобразований для компиляции — SomeType -> Inner -> Outer, Однако самое большее одно пользовательское преобразование может быть применено неявно.

Цитируя N3337, §12.3 [class.conv]

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

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


Если цель состоит в том, чтобы избежать упоминания Inner<SomeType> в операторе возврата вы можете использовать инициализацию списка.

Outer<Inner<SomeType>> DoSomethingWorks2() {
SomeType value;
return {std::move(value)};
}
6

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


По вопросам рекламы [email protected]