Substitution failure is not an error (SFINAE) for enum

c++, sfinae, traits

Solution

If you can use C++11, this is completely trivial:

template<class T>
struct has_nested_option{
  typedef char yes;
  typedef yes (&no)[2];

  template<class U>
  static yes test(decltype(U::option)*);
  template<class U>
  static no  test(...);

  static bool const value = sizeof(test<T>(0)) == sizeof(yes);
};

The C++03 version is (surprisingly) similar:

template<class T>
struct has_nested_option{
  typedef char yes;
  typedef yes (&no)[2];

  template<int>
  struct test2;

  template<class U>
  static yes test(test2<U::option>*);
  template<class U>
  static no  test(...);

  static bool const value = sizeof(test<T>(0)) == sizeof(yes);
};

Usage:

struct foo{
  enum { option = 1 };
};

struct bar{};

#include <type_traits>

template<class T>
typename std::enable_if<
  has_nested_option<T>::value
>::type Do(){
}

int main(){
  Do<foo>();
  Do<bar>(); // error here, since you provided no other viable overload
}

Problem

Is there a way to use Substitution failure is not an error (SFINAE) for enum? ``` template <typename T> struct Traits { } template <> struct Traits<A> { }; template <> struct Traits<B> { enum { iOption = 1 }; }; template <T> void Do() { // use Traits<T>::iOption }; ``` Then, `Do<B>();` works and `Do<A>();` fails. However, I can supply a default behavior when iOption does not exist. So I separate out some part of Do to DoOption. ``` template <typename T, bool bOptionExist> void DoOption() { // can't use Traits<T>::iOption. do some default behavior }; template <typename T> void DoOption<T, true>() { // use Traits<T>::iOption }; template <T> void Do() { // 'Do' does not use Traits<T>::iOption. Such codes are delegated to DoOption. DoOption<T, DoesOptionExist<T> >(); }; ``` Now, the missing piece is `DoesOptionExist<T>` - a way to check whether iOption exists in the struct. Certainly SFINAE works for function name or function signature, but not sure it works for enum value.

Original source