I have a class templated with typename T
. It contains a function,
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;
}
When I call this with, for example
myClass<double, 2> myObj_double_2(constructor args);
myObj_double_2 = myObj_double_2 + 5.2;
I have no problem.
If I however call
myObj_double_2 = myObj_double_2 + 5;
Then the compiler gives me a message like - 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')
.
Can I write the code in some way to allow additional types to be passed that have a conversion to T
(since, for example, double(5) is a valid constructor call)?
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 ::
.