Consider the following code:
#include <iostream>
#include <type_traits>
template <typename T>
class A
{
public:
// Allow func to be called if T is the const version of T2
// e.g., T is 'int const' and T2 is 'int'
template <typename T2,
typename = typename std::enable_if<
std::is_same<T, T2 const>::value>::type>
void func(A<T2> const &)
{
std::cout << "Conversion" << std::endl;
}
// Allow func to be called for same version of T
void func(A const &)
{
std::cout << "No conversion" << std::endl;
}
};
int main()
{
A<int const> a;
a.func(A<int const>{});
return 0;
}
This code, when compiled with GCC-8.3 compiles and produces the output No conversion
- it selected the version of func
that does not use std::enable_if
. However, if I comment out the second version of func
, it will still compile and now produce the output Conversion
. In other words, both versions of func
within A
are usable for this method. Given that both overloads are viable, what specific rule is the compiler using to select func(A const &)
over the other version (func(A<T2> const &)
)?
The rule is that if a non function template and a function template specialization have the same signature, then the non function template is chosen over the template specialization. This can be found in [over.match.best]/2
Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then
[...]
- F1 is not a function template specialization and F2 is a function template specialization [...]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With