I always thought that with templated functions, no implicit conversion may happen and the types of the arguments must exactly match the templated types of the parameters, or else the template argument deduction will fail.
Well, it seems I was mistaken.
Consider the following snippet:
#include <iostream>
#include <type_traits>
template <class T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
class myInt
{
T val;
public:
myInt(T val) : val(val) {}
template <class U, typename = typename std::enable_if<std::is_integral<U>::value>::type>
friend bool operator < (myInt<T> const &t, myInt<U> const &u)
{
return t.val < u.val;
}
};
int main()
{
myInt<int> i = 5;
myInt<int> j = 6;
// std::cout << (i < 6) << std::endl; // gives out compiler errors
std::cout << (5 < j) << std::endl; // works!
}
I'm not sure why does the second std::cout << (5 < j)
work. Implicit conversion must have happened here, which I thought was prohibited. And I'm even less sure why doesn't the std::cout << (i < 6)
work if the former one does!
Edit: Compiler errors for std::cout << (i < 6)
:
test.cpp: In function ‘int main()’:
test.cpp:23:21: error: no match for ‘operator<’ (operand types are ‘myInt<int>’ and ‘int’)
std::cout << (i < 6) << std::endl; // gives out compiler errors
^
test.cpp:23:21: note: candidate is:
test.cpp:12:17: note: template<class U, class> bool operator<(const myInt<int>&, const myInt<T>&)
friend bool operator < (myInt<T> const &t, myInt<U> const &u)
^
test.cpp:12:17: note: template argument deduction/substitution failed:
test.cpp:23:23: note: mismatched types ‘const myInt<T>’ and ‘int’
std::cout << (i < 6) << std::endl; // gives out compiler errors