Given this code:
class X
{
public:
template< typename T >
void func( const T & v );
};
template<>
void X::func< int >( const int & v )
{
}
template<>
void X::func< char * >( const char * & v ) // 16
{
}
When I compile it I get the following error.
test.cpp:16: error: template-id 'func<char*>' for 'void X::func(const char*&)' does not match any template declaration
Can anyone shed any light on this?
There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.
You can choose to specialize only some of the parameters of a class template. This is known as partial specialization. Note that function templates cannot be partially specialized; use overloading to achieve the same effect.
A template function can be overloaded either by a non-template function or using an ordinary function template.
The class template in c++ is like function templates. They are known as generic templates. They define a family of classes in C++. Here Type is a placeholder type name, which will be specified when a class instantiated.
If you change the declaration:
template<> void X::func< char * >( const char * & v )
to:
template<> void X::func< char * >( char * const & v )
This would work perfectly fine. Why does it happen? Because while const sometype
is perfectly acceptable, it's only an alternative notation for sometype const
. So, your const modifier is not applied to the basic type (char
), but to the pointer, making "constant pointer to non-constant char" a valid type. If that's not what you want, you'll have to correct your basic template.
Finally, here's some interesting reading for you about why overloading templates is generally better than specializing them.
The reason you face this error is because you write const
before the type. Although this is common practise, it is not conducive to understanding how const/volatile-qualifiers (cv-qualifier) work.
In this case const T
when T
is char*
doesn't mean const char*
. It rather means char* const
because T
is char*
and no matter which side of T
you put const
it behaves as if const
is on the right of T
, that is, the pointer itself that is going to be const not the type pointed too.
It is easy to avoid this type of confusion if you make it a rule to always put const
or volatile
on the right of the type. For example, it makes it straightforward to mentally expand T const
when T
is char*
to char* const
.
This is the reason in boost sources you see cv-qualifiers after the type, not before.
Move const
before &
template<>
void X::func< char * >( char * const & v )
{
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With