Почему моя шаблонная функция не переводит int в T, где T = double?

У меня есть класс по шаблону typename T, Он содержит функцию,

template <typename T, size_t a>
myClass<T,a> operator+(myClass<T,a> lhs, const T& rhs) {
return lhs += rhs;
}

myClass<T,a> myClass<T,a>::operator+=(const T& rhs) {
// Do addition, depends on 'a'.
return *this;
}

Когда я называю это с, например,

myClass<double, 2> myObj_double_2(constructor args);
myObj_double_2 = myObj_double_2 + 5.2;

У меня нет никакой проблемы.

Если я однако позвоню

myObj_double_2 = myObj_double_2 + 5;

Затем компилятор выдает мне сообщение вроде — No match for 'operator+' (operand types are 'myClass<double, 2ul>' and 'int'). Candidates are ... note: deduced conflicting types for parameter 'const T' ('double' and 'int'),

Могу ли я написать код для передачи дополнительных типов, которые имеют преобразование в T (поскольку, например, double (5) является допустимым вызовом конструктора)?

21

Решение

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

В вашем случае два вычета для T производить double а также int, которые не совпадают, и поэтому вычет не удается.

Что вы можете сделать, это только использовать один аргумент функции для вывода аргумента шаблона, и сделать другой undeduced:

template <typename T, std::size_t A>
void foo(myClass<T, A> arg1, typename std::common_type<T>::type arg2);
//                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Обратите внимание, что std::common_type<T>::type по сути просто T, но потому что тип arg2 теперь является зависимым типом (его имя отображается справа от ::), это не выводится. Следовательно, только первый аргумент принимает участие в выводе и производит T = double однозначно, а то второй параметр функции просто имеет тип doubleи обычные преобразования происходят.

Как правило, вывод аргументов шаблона не пересекается ::,

32

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

Компилятор по разрешению перегрузки не может найти подходящего кандидата для operator+ так как T уже вычитается double и буквальный 5 является целым числом Решение:

template <typename T1, typename T2, size_t a>
myClass<T1,a> operator+(myClass<T1,a> lhs, const T2& rhs) {
return lhs += T1(rhs);
}
17

У вас проблемы с вычетом типа шаблона.

Оба аргумента имеют «равное положение» при выводе значения Tи в этом случае два аргумента расходятся — один говорит T должно быть intдругой говорит T должно быть double,

Правильный способ исправить это с помощью операторов Кенига.

Делать += а также + и тому подобное friendс вашего класса и реализовать встроенный:

template<class T, size_t a>
class myClass {
// etc
public:
friend myClass operator+(myClass lhs, const T& rhs) {
lhs += rhs;
return std::move(lhs);
}
friend myClass& operator+=(myClass& lhs, const T& rhs) {
// do addition, depends on `a`
return *this;
}
};

эта техника делает что-то странное. Это создает неtemplate операторы, основанные на типе шаблона класса. Затем они обнаруживаются через ADL (поиск Кенига), когда вы вызываете + или же +=,

Вы получаете один из этих операторов для каждого экземпляра шаблона, но они не являются операторами шаблона, поэтому const T& не выводится, и преобразование происходит, как ожидалось.

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