Can't specialize template?

1
2
3
4
5
6
7
8
template<typename T>
void f(const T &t)
{
}
template<>
void f<char *>(const char *cstr) //error: does not match any template declaration
{
}
This is a new one for me, and I couldn't really find much info on it with some searching. What's causing it?

Intended behavior is that only these parameter types call the second version:
char *
const char *
char *const
const char *const
Last edited on
1
2
3
4
5
6
7
8
9
10
template<typename T> void f( const T& t ) {}

// specialization: T => char* and const T& (T const&) => char* const&
template<> void f<char*>( char* const& cstr) {}

// we could use a typedef to make things easier
template<typename T> void g( const T& t ) {}

using cstr_t = char* ;
template<> void g( const cstr_t& t ) {}


In general, prefer overloading function templates. Specializations of function templates work in ways that are not intuitive to most programmers.
http://www.gotw.ca/publications/mill17.htm


> Intended behavior is that only these parameter types call the second version:

1
2
3
4
5
template< typename T > int h( const T& t ) {  return 0 ; }

int h( const char* cstr ) { return 1 ; }

int h( char* cstr ) { return h( const_cast<const char*>(cstr) ) ; }

Last edited on
Thanks! But I do have a question: Why is it called 'overloading function templates' if it's the functions instantiated from the templates that get overloaded and not the templates themselves?

Also, in my real case I'm overloading an operator that can only take one parameter, so it's pretty unfeasible to overload the function template.
> Why is it called 'overloading function templates' if it's the functions instantiated from the templates that get overloaded

Only the function template that is selected after partial ordering and overload resolution is instantiated.

1
2
3
4
5
6
7
template < typename T > void foo( T a ) { a.this_is_an_error_if_T_is_int() ; }
template < typename T, typename U > void foo( T a, U b ) {}

int main()
{
    foo(22,33) ; // ok: only the second overload is instantiated 
}



> Also, in my real case I'm overloading an operator that can only take one parameter, so it's pretty unfeasible to overload the function template.

Specialize the class template instead?
It wouldn't make sense to have a FileStream<int>
(and wouldn't work either)
Last edited on
Just overload the overloaded operator:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

struct A
{
    template < typename T > void operator<< ( const T& v ) { std::cout << v << '\n' ; }
    void operator<< ( const char* const& v ) { std::cout << v << " (const char*)\n" ; }
    void operator<< ( char* const& v ) { std::cout << v << " (char*)\n" ; }
};

int main()
{
    A a ;
    int i = 100 ; a << i  ; // 100
    char msg[] = "hello world" ; a << msg ; // hello world (char*)
    a << "hello again " ; // hello again  (const char*)
}
Huh, I thought I tried that once and it didn't work and I asked about it on here and people told me it wasn't possible. But that still causes issues if you explicitly use the template brackets (which happens in some cases with other code I cannot control). I'll keep that in mind for the future though!
Topic archived. No new replies allowed.