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::foo
valid, check if member static or not usingstd::is_member_pointer
(your version). - if
&t::foo
not valid, falls second overload (here surefoo
not static, or first overload have been chosen):- if
t::foo
valid (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::foo
valid, 2 first overloads valid, first 1 chosen sinceint
exact match whilelong
not. decltype(t::foo, std::true_type{})
:t::foo
here "let sfinae" fall third overload ift::foo
not valid, resulting typestd::true_type
comma 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