简体   繁体   中英

Trait template class for checking if a class has a member with specific name

I made this code for checking if a class has a member called first:

template <class T>
struct ClassA{
    T first;
};

template <class T>
struct ClassB{
    T second;
};

template <class T>
struct has_member_named_first
{
    typedef char valid_type;
    typedef struct { char array[2]; } not_valid_type;

    template <typename U>
    static valid_type __test(typename U::first*);

    template <typename U>
    static not_valid_type __test(...);

    static const bool value = sizeof(__test<T>(0)) == sizeof(valid_type);
};

By defining valid_type as char and not_valid_type as struct { char array[2]; } we can make the last line sizeof(__test<T>(0)) == sizeof(valid_type); return true or false based on the instantiated function __test and thus determine if a class has a member named first .

int main()
{
   std::cout << has_type_named_first<ClassA<int> >::value << std::endl;
   std::cout << has_type_named_first<ClassB<int> >::value << std::endl;
   return (0);
}

but i got in the output:

0

0

In C++98, checks for if an expression is valid using SFINAE can be done like this:

template <class T>
struct has_member_named_first
{
private:
    typedef char valid_type;
    typedef char(&not_valid_type)[2];

    template<std::size_t> struct check_expr;

    template <typename U>
    static valid_type test(check_expr<sizeof((void) (YOUR_EXPRESSION_HERE), 0)>*);

    template <typename U>
    static not_valid_type test(...);

public:
    static const bool value = sizeof(test<T>(0)) == sizeof(valid_type);
};

To check for a data member, you can have YOUR_EXPRESSION_HERE be static_cast<U*>(0)->first or simply U::first .

To check for a member function or data member, use &U::first .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM