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 typedef
s (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.