how to implement "contains a member" template ?

G

Gianni Mariani

I remember seeing a neat template specialization trick posted here a few
months ago that allowed the detection of a type containing a member.
After a day searching through google archives I come up zip.


Anyhow, after much trial and error I came up with this. This
"contains_member" template sets value to 1 if the type D contains
a typedef named MEMBER of type TD.


============== example.cpp ==================

template <typename D, typename TD = int >
struct contains_member
{

struct false_t { char m[2]; };
typedef char true_t;

struct XX : D
{
};

struct finder_s
{

template <typename T>
static true_t finder( const T *, typename T::MEMBER );

static false_t finder( const D *, int );

};

typedef XX * XXp;

enum {
value =
sizeof( finder_s::finder( XXp(), TD() ) ) == sizeof( true_t )
};


};


struct A
{
virtual void f() = 0;
};

struct B
: A
{
virtual void f() = 0;

typedef int MEMBER;
};

struct C
{
typedef short MEMBER;
};



#include <iostream>


int main()
{
std::cout << contains_member< B >::value << "\n";
std::cout << contains_member< A >::value << "\n";
std::cout << contains_member< C, short >::value << "\n";
}

============== end example ==============



Now I try to set make it more generic by allowing any member name.
To do this I pass in a template template parameter that has a typedef
that uses the member name. This does not work because during the
attempt to instantiate the template "member" there is an error.

So, this seems inconsistent. In the previous example, the compiler
does not even bother because the template function finder can't be
resolved while in the second case it also can't be resolved but it dumps
an error.

This is consistent with gcc 3.4.0, msc++ 7.1 and Comeau C/C++ 4.3.3.


============== example2.cpp =============

template <typename D>
struct member
{
typedef typename D::MEMBER type;
};



template <typename D, typename TD = int, template <typename> class MEM =
member >
struct contains_member
{

struct false_t { char m[2]; };
typedef char true_t;

struct XX : D
{
};

struct finder_s
{

template <typename T>
static true_t finder( const T *, typename MEM<T>::type );

static false_t finder( const D *, int );

};

typedef XX * XXp;

enum {
value =
sizeof( finder_s::finder( XXp(), TD() ) ) == sizeof( true_t )
};


};


struct A
{
virtual void f() = 0;
};

struct B
: A
{
virtual void f() = 0;

typedef int MEMBER;
};

struct C
{
typedef int OTHERMEMBER;
};


template <typename D>
struct othermember
{
typedef typename D::OTHERMEMBER type;
};



#include <iostream>


int main()
{

std::cout << contains_member< B >::value << "\n";
std::cout << contains_member< A >::value << "\n";
std::cout << contains_member< C, int, othermember >::value << "\n";

}

====================================

Any easier way to do this ?
 

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

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top