I’m trying to specialize a template member function of a non-template class using a templatized parameter:
#include <array>
class C
{
public:
template<class Container>
void Foo( Container& )
{
// ...
}
};
template<class T, std::size_t N>
template<>
void C::Foo< std::tr1::array<T,N> >( std::tr1::array<T,N>& )
{
// special
}
I get an error “illegal use of explicit template arguments” with this. What’s the right syntax to make this valid?
Update:
Perhaps I’ve muddled the issue by over-simplifying. What I really want to do is specially handle this one case where there is a dependent name involved, which I think may be what is throwing a monkey wrench into the works here. My original thought was to overload the function as such:
class C
{
public:
template<class Iter>
void Foo( Iter )
{
std::cout << "Normal\n";
}
template<class T, std::size_t N>
void Foo( typename std::tr1::array<T,N>::iterator )
{
std::cout << "Special\n";
}
};
int main()
{
C c;
std::tr1::array<int,10> a1;
c.Foo( a1.begin() ); // Doesn't print "Special"!
}
But the special Foo doesn’t get called. How can I do that?
Only the member function is templated, which means that you should only use one
template<...>in there. But that will not solve it either, as you cannot partially specialize a function.The usual way of handling the problem is through overloads, rather than specialization (specialization of template functions is not that useful).
Note that the difference is that they are two separate template functions (rather than an specialization).
EDIT: After the update
The update to the question changes the problem completely. The problem that you are seeing is that the argument of the second version is a dependent name, and as such it is non deducible. Given the function call the compiler is not able to determine what type T, and integral constant N are to match that particular instantiation. Consider a different example:
When the compiler processes the call in
main, it instantiates the template and extracts the type, from that it creates a temporary, and then it tries to decide what to do withfoobut at that time it only knows that it is being called with anintrvalue… the originalinner<double>::typeis gone, now it is justfoo( int() )and the compiler would have to try and instantiateinner_intwith all possible types to determine whether any of them fits, and in the worse case, as above, many would match.