c++ - Type trait: Check if reference member variable is static or not -
i check if member variable of class static or not. using std::is_member_pointer works fine types except reference members.
#include <type_traits> struct { int foo; }; struct b : {}; struct c { static int foo; }; struct d : c { }; struct e { int &foo; }; struct f { static int &foo; }; static_assert(std::is_member_pointer<decltype(&a::foo)>::value, "no"); static_assert(std::is_member_pointer<decltype(&b::foo)>::value, "no"); static_assert(!std::is_member_pointer<decltype(&c::foo)>::value, "no"); static_assert(!std::is_member_pointer<decltype(&d::foo)>::value, "no"); // fail compile: static_assert(std::is_member_pointer<decltype(&e::foo)>::value, "no"); static_assert(!std::is_member_pointer<decltype(&f::foo)>::value, "no"); i understand error, pointer cannot point reference member. how avoid , still distinguish if static or non static variable? idea on that?
you add fallback in case &e::foo fails using sfinae (and 1 in case e::foo not exist @ all):
template <typename t> std::is_member_pointer<decltype(&t::foo)> is_member_foo(int); template <typename t> decltype(t::foo, std::true_type{}) is_member_foo(long); template <typename t> std::false_type is_member_foo(...); template <typename t> using ismemberfoo = decltype(is_member_foo<t>(0)); static_assert(ismemberfoo<a>{}, "no"); static_assert(ismemberfoo<b>{}, "no"); static_assert(!ismemberfoo<c>{}, "no"); static_assert(!ismemberfoo<d>{}, "no"); static_assert(ismemberfoo<e>{}, "no"); static_assert(!ismemberfoo<f>{}, "no"); static_assert(!ismemberfoo<g>{}, "no"); // struct g { }; what code does:
- if
&t::foovalid, check if member static or not usingstd::is_member_pointer(your version). - if
&t::foonot valid, falls second overload (here surefoonot static, or first overload have been chosen):- if
t::foovalid (a member exists), returnsstd::true_type. - otherwize falls last overload , returns
std::false_type.
- if
also note (thanks @iammilind) private member, t::foo not valid, third overload chosen.
working example on ideone: http://ideone.com/filhbk
side notes (extended explanation):
- when
&t::foovalid, 2 first overloads valid, first 1 chosen sinceintexact match whilelongnot. decltype(t::foo, std::true_type{}):t::foohere "let sfinae" fall third overload ift::foonot valid, resulting typestd::true_typecomma operator.
if like, can create generic version (http://ideone.com/lzh2fb):
#define ismember(mem) \ template <typename t> \ std::is_member_pointer<decltype(&t::mem)> is_member_##mem(int); \ template<typename t> \ decltype(t::mem, std::true_type{}) is_member_##mem(long); \ template <typename t> \ std::false_type is_member_##mem(...); \ template <typename t> \ using ismember_##mem = decltype(is_member_##mem<t>(0)); // instanciate ismember_foo ismember(foo); // use it: static_assert(ismember_foo<a>{}, "no"); also see these 2 answers if want encapsulate in class (without having is_member_ functions):
Comments
Post a Comment