in template overloading, "hi" isn't char* type?

Apr 25, 2013 at 7:01am
Write your question here.

i set up 2 templates, 1 of the 2 is a explicit specialization.
1
2
template <typename T> void iquote(T); //#1
template <> void iquote<char*>(char* x); //#2 

i hope when i give, say, 10, 10.0, the program would choose #1, and when i give "hey", it will choose #2, but the result is that, it still choose #1, only when i give variable whose type is char* will choose #2.
i was told "hey" and char* x; both char* type and cause they are actually the addr. i'm puzzled...
and how i code is the right way?
Last edited on Apr 25, 2013 at 7:02am
Apr 25, 2013 at 7:07am
"hi" is of type const char[3] so you should specialize on const char*, otherwise the unspecialized version will be a better match.
Last edited on Apr 25, 2013 at 7:09am
Apr 25, 2013 at 7:12am
Add one more template specialization

template <> void iquote<const char*>(const char* x); //#3

Apr 25, 2013 at 7:40am
wow, thx!
Apr 25, 2013 at 7:58am
As far as possible, avoid specializing function templates.

In this case for instance, specialization(s) are completely unnecessary.
1
2
3
template <typename T> void iquote(T) ; 
void iquote( char* ) ; 
void iquote( const char* ) ;


To understand why specializing function templates is a bad idea, see:
http://www.gotw.ca/publications/mill17.htm

Apr 25, 2013 at 2:21pm
To understand why specializing function templates is a bad idea, see:
http://www.gotw.ca/publications/mill17.htm


Thanks for the link. Always good stuff.
Apr 25, 2013 at 3:08pm
The downside to preferring overloading over specializing is that you can still call the template version if you explicitly specify the template args (which may sometimes be necessary to avoid ambiguities)

1
2
3
4
5
6
7
8
9
10
template <typename T> void f(T);  // (a)
void f(int);  // (b)


template <typename T>  // for this example, assume T=int
void problematic_function()
{
    T foo;
    f<T>(foo);  // calls (a), not (b)
}


Obviously this is a trivial example because <T> doesn't need to be explicitly specified here... but sometimes it needs to be.


Perhaps the best would be to do both?

1
2
3
4
template <typename T> void f(T);
void f(int);

template <> void f<int>(int x) { f(x); }
Last edited on Apr 25, 2013 at 3:09pm
Apr 25, 2013 at 4:42pm
> Perhaps the best would be to do both?

It is a poor design idea to demand that users must do two different things in tandem to achieve something that can be achieved by doing just one.

The canonical solution to this problem (and also the problem that function templates can't be partially specialised) is given in the link I had posted earlier. With apologies to those who had read it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>

template < typename T > struct ff ;

template <typename T> void f( T t ) { ff<T>::f(t) ; }

template < typename T > struct ff
{ static void f(T) { std::cout << "general\n" ; } } ;

template < typename T > struct ff<T*>
{ static void f(T*) { std::cout << "partial for pointers\n" ; } } ;

template <> struct ff<int>
{ static void f(int) { std::cout << "complete for int\n" ; } } ;

int main()
{
    f('a') ; // general
    int a = 8 ;
    f(a) ; // complete for int
    f(&a) ; // partial for pointers
}


http://ideone.com/FYFFhF
Apr 25, 2013 at 5:46pm
I had read the link, I guess I just stopped before the "Moral 2" part.

Very interesting indeed.
Topic archived. No new replies allowed.