There is a strong difference between a pointer to a constant object (T const*, or const T*) and a constant pointer to a non-constant object (T * const). In your case the signature of the member Add is:
void Foo<char *>::Add(char * const& ); // reference to a constant pointer to a
// non-constant char
I usually recommend that people drop the use of const on the left hand side exactly for this reason, as beginners usually confuse typedefs (or deduced types) with type substitution and when they read:
const T& [T == char*]
They misinterpret
const char*&
If the const is placed in the right place:
T const &
Things are simpler for beginners, as plain mental substitution works:
char * const &
A different problem than what you are asking, but maybe what you think you want, is:
Given a type T have a function that takes a U that is const T if T is not a pointer type, or X const * if T is a pointer to X
template <typename T>
struct add_const_here_or_there {
typedef T const type;
};
template <typename T>
struct add_const_here_or_there<T*> {
typedef T const * type;
};
Then you can use this in your signature:
template <typename T>
void Foo<T>::Add( const typename add_const_here_or_there<T>::type & arg ) {
...
Note that I am adding two const in the signature, so in your case char* will map to char const * const &, as it seems that you want to pass a const& to something and you also want the pointed type to be const.
You might have wondered as of the name for the metafunction: *add_const_here_or_there*, it is like that for a reason: there is no simple way of describing what you are trying to do, which is usually a code smell. But here you have your solution.