Reputation: 69988
I was trying to implement a meta-program which finds if given pointer type is const
or not. i.e.
is_const<TYPE*>::value
should be false
is_const<const TYPE*>::value
should be true
Following is the code:
template<class TYPE>
struct is_const
{
typedef char yes[3];
template<typename T>
struct Perform
{
static yes& check (const T*&);
static char check (T*&);
};
TYPE it;
enum { value = (sizeof(Perform<TYPE>::check(it)) == sizeof(yes)) };
};
And the compiler error messages are:
In instantiation of ‘is_const<int*>’:
instantiated from here
error: no matching function for call to ‘is_const<int*>::Perform<int*>::check(int*&)’
note: candidates are: static char (& is_const<TYPE>::Perform<T>::check(const T*&))[3] [with T = int*, TYPE = int*]
note: static char is_const<TYPE>::Perform<T>::check(T*&) [with T = int*, TYPE = int*]
My focus has shifted to the error message. If you see the last line:
note: static char is_const<TYPE>::Perform<T>::check(T*&) [with T = int*, TYPE = int*]
If we really replace T = int*
and TYPE = int*
then it really should match the appropriate function (char check()
). I am anxious to know that what is going wrong here.
Upvotes: 3
Views: 200
Reputation: 133014
THere are two things wrong in your code.
First, the following
static yes& check (const T*&);
static char check (T*&);
must be changed to
static yes& check (const T&);
static char check (T&);
Ans second, the it
member must be static
static TYPE it;
or, just pass ((TYPE)0)
to your check function. No need of the member.
Upvotes: 1
Reputation: 26853
Here's your problem:
static yes& check (const T*&);
static char check (T*&);
When you instantiate is_const<int*>
, your function definitions are expanded to:
static yes& check (const int**&);
static char check (int**&);
However, your temporary item (TYPE it
) is of type int*
, like you specified. You need to change your check
function signatures to remove the pointer specifier, like so:
static yes& check (const T&);
static char check (T&);
Upvotes: 1
Reputation: 477060
Why so roundabout? How about a straight-forward trait class:
#include <functional>
template <typename T> struct is_const_ptr : std::false_type { };
template <typename T> struct is_const_ptr<const T *> : std::true_type { };
struct Foo {};
int main()
{
std::cout << is_const_ptr<Foo*>::value << is_const_ptr<const Foo*>::value << std::endl;
}
Upvotes: 9