开发者

using templates to check for member variable not working on int

开发者 https://www.devze.com 2023-03-24 05:05 出处:网络
I need to check and see if a given type has a member variable. However when a type that is not a class or a struct is given, I get a compiler error.

I need to check and see if a given type has a member variable. However when a type that is not a class or a struct is given, I get a compiler error.

struct Vector {
    int x;
};

template <typename Type>
class has_member_x
{
   class yes { char m;};
   class no { yes m[2];};

   struct BaseMixin
   {
     int x;
   };

   struct Base : public Type, public BaseMixin {};

   template <typename T, T t>  class 开发者_如何学GoHelper{};

   template <typename U>
   static no deduce(U*, Helper<void (BaseMixin::*)(), &U::x>* = 0);
   static yes deduce(...);

public:
   static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0)));

}; 

int main() {

    BOOST_STATIC_ASSERT(has_member_x<int>::result);
    BOOST_STATIC_ASSERT(has_member_x<Vector>::result);
}

When I try to compile this it fails with the following error.

error: base type ‘int’ fails to be a struct or class type

Is there a way that this can be done in either c++ or c++0x?


After fixing a bug in the original has_member_x class, and adding specialization for class types as it was suggested by others the final working version looks like this:

#include <type_traits>

template <typename Type, bool Enabled = std::is_class<Type>::value>
class has_member_x
{
public:
   static const bool result = false;
}; 

template <typename Type>
class has_member_x<Type, true>
{
   class yes { char m;};
   class no { yes m[2];};

   struct BaseMixin
   {
     int x;
   };

   struct Base : public Type, public BaseMixin {};

   template <typename T, T t>  class Helper{};

   template <typename U>
   static no deduce(U*, Helper<int BaseMixin::*, &U::x>* = 0);
   static yes deduce(...);

public:
   static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0)));
}; 


You can use boost::enable_if and boost::type_traits, specifically boost::is_integral or boost::is_class for this.

Try this(I have not tested it, but this should give you the idea.):

struct Vector {
    int x;
};

template <typename Type, typename Enabled = void>
class has_member_x
{
public:
   static const bool result = false;
}; 

template <typename Type, typename Enabled = boost::enable_if<boost::is_class<Type> >::type > 
class has_member_x
{
   class yes { char m;};
   class no { yes m[2];};

   struct BaseMixin
   {
     int x;
   };

   struct Base : public Type, public BaseMixin {};

   template <typename T, T t>  class Helper{};

   template <typename U>
   static no deduce(U*, Helper<void (BaseMixin::*)(), &U::x>* = 0);
   static yes deduce(...);

public:
   static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0)));

}; 

int main() {

    BOOST_STATIC_ASSERT(has_member_x<int>::result);
    BOOST_STATIC_ASSERT(has_member_x<Vector>::result);
}
0

精彩评论

暂无评论...
验证码 换一张
取 消