1

I am trying to do the following: a templated class should provide some functions dependend on whether or not the type it has been templated with contains a member variable with a given name. As example the following pseudocode which should provide "printid()" only when templated struct/class has a member called "id":

#include <iostream>
#include <type_traits>

struct A { int id; };
struct B { };

template<typename T>
class foo
{
  T myvar;

public:
  #if exists T.id   (or the alternative: #if exists myvar.id)
  printid() { std::cout << "I have element id."; }
  #endif
};

int main(){
  foo<A> ok;
  ok.printid();   // should compile and execute

  foo<B> nok;
  nok.printid();  // should not compile
  return 0;
}

Digging around SFINAE, traits, std::enable_if and StackOverflow, I think it can be done ... somehow. But I somehow fail to combine enable_if with the the following snippet from the question How to detect whether there is a specific member variable in class?:

template<typename T, typename = void>
struct has_id : std::false_type { };

template<typename T>
struct has_id<T, decltype(std::declval<T>().id, void())> : std::true_type { };

Any help appreciated.

Community
  • 1
  • 1
BaCh
  • 625
  • 2
  • 5
  • 17

1 Answers1

3

Yep, it's possible. Here's an example:

template<typename T>
class foo
{
  T myvar;

public:
  template <class _T = T,
            class = typename std::enable_if<
                      !std::is_function<decltype(_T::id)>::value>
                    ::type>
  void printid() { std::cout << "I have element id."; }
};

Specifically, note how we're "taking in" T as _T in order to not force a constraint on the class template parameter (which would make the class itself un-compileable). Instead, we're creating a new, independent template member function, which doesn't force anything on T itself—it just "happens to" use it as a default argument. That's the key part.

Yam Marcovic
  • 7,953
  • 1
  • 28
  • 38
  • 1
    Works as intended. I never would have found out how to declare this voodoo. Wrapping this in a define to save typing for multiple functions is now a piece of cake. Thank you very much. – BaCh Jan 27 '16 at 20:16