I have a class templated with typename T
. It contains a function,
template
myClass operator+(myClass
The compiler on overload resolution fails to find a right candidate for operator+
because T
is already being deducted to double
and literal 5
is an integer. Solution:
template <typename T1, typename T2, size_t a>
myClass<T1,a> operator+(myClass<T1,a> lhs, const T2& rhs) {
return lhs += T1(rhs);
}
When you are using template argument deduction, all deductions for one template parameter must have the same result.
In your case, the two deductions for T
produce double
and int
, which are not the same, and so deduction fails.
What you can do is only use one function argument for template argument deduction, and make the other one undeduced:
template <typename T, std::size_t A>
void foo(myClass<T, A> arg1, typename std::common_type<T>::type arg2);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note that std::common_type<T>::type
is essentially just T
, but because the type of arg2
is now a dependent type (its name appears to the right of a ::
), it is not deduced. Therefore, only the first argument takes part in deduction and produces T = double
unambiguously, and then the second function parameter just has type double
, and the usual conversions take place.
As a rule of thumb, template argument deduction does not cross ::
.
You are running into problems with template type deduction.
Both arguments are given "equal standing" when deducing the value of T
, and in this case the two arguments disagree -- one says T
should be int
, the other says T
should be double
.
The right way to fix this is with Koenig operators.
Make +=
and +
and the like friend
s of your class and implement inline:
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;
}
};
this technique does something strange. It creates non-template
operators based on the template type of the class. These are then found via ADL (Koenig lookup) when you invoke +
or +=
.
You get one of these operators per template instantiation, but they aren't template operators, so const T&
isn't deduced, and conversion happens as expected.