Let's say I have a class template
template <class Ta>
struct Base {};
And I've written some overloaded function templates around it:
template <class T1, class T2>
void f(Base<T1>&, T2){
std::cout << "1" << std::endl;
}
template <class T1, class T2>
void f(Base<T1>&, Base<T2>&){
std::cout << "2" << std::endl;
}
When I invoke the functions:
Base<float> base1;
Base<float> base2;
f(base1,1);
f(base1,base2);
I get exactly what I'd expect:
1
2
All is well, but now I want to create a derived class:
template <class Ta, class Tb>
struct Derived : Base<Ta> {};
All of a sudden, when I run the same code on instances of the derived class:
Derived<float,int> derived1;
Derived<float,int> derived2;
f(derived1,1);
f(derived1,derived2);
I get a different result:
1
1
Apparently, the compiler interprets T2=Derived<Ta,Tb>
, and does not interpret the alternate overload as having greater specificity.
What is the best way to clarify to the compiler that calls to f(derived1,derived2)
should be interpreted as calls to f(Base<T1>, Base<T2>)
?
Full minimal example
#include <iostream>
template <class Ta>
struct Base {};
template <class Ta, class Tb>
struct Derived : Base<Ta> {};
template <class T1, class T2>
void f(Base<T1>&, T2){
std::cout << "1" << std::endl;
}
template <class T1, class T2>
void f(Base<T1>&, Base<T2>&){
std::cout << "2" << std::endl;
}
int main()
{
Base<float> base1;
Base<float> base2;
f(base1,1);
f(base1,base2);
Derived<float,int> derived1;
Derived<float,int> derived2;
f(derived1,1);
f(derived1,derived2);
}