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"); 

live example.

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 using std::is_member_pointer (your version).
  • if &t::foo not valid, falls second overload (here sure foo not static, or first overload have been chosen):
    • if t::foo valid (a member exists), returns std::true_type.
    • otherwize falls last overload , returns std::false_type.

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 since int exact match while long not.
  • decltype(t::foo, std::true_type{}): t::foo here "let sfinae" fall third overload if t::foo not valid, resulting type std::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

Popular posts from this blog

Ansible - ERROR! the field 'hosts' is required but was not set -

customize file_field button ruby on rails -

SoapUI on windows 10 - high DPI/4K scaling issue -