template specialization problem, but only with char*

A

Adam

I'm trying to write a template specialization, and the char*
specialization is giving me some trouble. Here's a simplified example:

/**************************/
/* test.cpp */
#include "try.hpp"

int main(){}
/**************************/

/**************************/
/* try.hpp */

template <typename T> struct foo
{
void f(const T& param) const;
};

template <typename T>
void
foo<T>::f(const T& param) const
{}

template <> // works fine
void
foo<int>::f(const int& param) const
{}

/*
The following results in:

template-id `f<>' for `void foo<char*>::f(const char*&) const' does not
match any template declaration

template <>
void
foo<char*>::f(const char*& param) const
{}
*/

/*
The following results in:
template-id `f<>' for `void foo<char*>::f(const char*) const' does not
match any template declaration

template <>
void
foo<char*>::f(const char* param) const
{}
*/

/*
But the following works fine. That really confuses me....
*/
typedef char* Char;

template <>
void
foo<Char>::f(const Char& param) const
{}

/**************************/
Thanks for reading. Any help would be greatly appreciated.

- Adam
 
V

Victor Bazarov

Adam said:
I'm trying to write a template specialization, and the char*
specialization is giving me some trouble. Here's a simplified example:

/**************************/
/* test.cpp */
#include "try.hpp"

int main(){}
/**************************/

/**************************/
/* try.hpp */

template <typename T> struct foo
{
void f(const T& param) const;
};

template <typename T>
void
foo<T>::f(const T& param) const
{}

template <> // works fine
void
foo<int>::f(const int& param) const
{}

/*
The following results in:

template-id `f<>' for `void foo<char*>::f(const char*&) const' does not
match any template declaration

template <>
void
foo<char*>::f(const char*& param) const
{}
*/

/*
The following results in:
template-id `f<>' for `void foo<char*>::f(const char*) const' does not
match any template declaration

template <>
void
foo<char*>::f(const char* param) const
{}
*/

/*
But the following works fine. That really confuses me....
*/
typedef char* Char;

template <>
void
foo<Char>::f(const Char& param) const
{}

/**************************/

'const' relates to the object, not to the type. In all fairness, it
should be placed to the right of the type. In your case, this is what
your [working] declaration should be

template<> void foo<char*>::f(char* const & param);

and you tried [unsuccessfully] to declare it as

template<> void foo<char*>::f(char const *& param);

Do you see the difference?

In your template, it's the object who is const. So, the reference that
'param' designates _refers_ to a constant something. In your 'char*'
specialisation, that something is a _pointer_to_char_. So, you have to
make your _pointer_ constant. You've been trying to make the _char_
constant and leave the pointer non-const. That's the mistake.

V
 
A

Adam

'const' relates to the object, not to the type. In all fairness, it
should be placed to the right of the type. In your case, this is what
your [working] declaration should be

template<> void foo<char*>::f(char* const & param);

and you tried [unsuccessfully] to declare it as

template<> void foo<char*>::f(char const *& param);

Do you see the difference?

I do.

Thanks, Victor.

It is no longer relevant to this particular problem, but I am curious
as to why the following worked:

typedef char* Char;
template<> void foo<Char>::f(const Char& param);

How is 'const Char &' different from 'const char* &' in this case? I'm
guessing that 'Char' is now seen only as a pointer, and that 'const
Char' is equivalent to 'Char const'. Is that correct?

- Adam
 
V

Victor Bazarov

Adam said:
[...]
It is no longer relevant to this particular problem, but I am curious
as to why the following worked:

typedef char* Char;
template<> void foo<Char>::f(const Char& param);

How is 'const Char &' different from 'const char* &' in this case? I'm
guessing that 'Char' is now seen only as a pointer, and that 'const
Char' is equivalent to 'Char const'. Is that correct?

Absolutely. You always should position the 'const' specifier to the right
of the type-id. In case of 'char*', the type-id is 'char', so the 'const'
moves between 'char' and '*'. In case of 'Char', the type-id is 'Char',
so the 'const' skips to the right. Once expanded again, it becomes this
peculiar thing 'char * const', which is not the same as 'char const *'.

It's not the clearest part of the language, but once you learn it, it will
serve you well.

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top