Ошибка замены не является ошибкой (SFINAE) для enum - PullRequest
3 голосов
/ 22 декабря 2011

Есть ли способ использовать Ошибка замещения - это не ошибка (SFINAE) для 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
};

Тогда Do<B>(); работает и Do<A>(); не срабатывает.Тем не менее, я могу предоставить поведение по умолчанию, когда iOption не существует.Поэтому я выделяю некоторую часть 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> >();
};

Теперь недостающий фрагмент - DoesOptionExist<T> - способ проверить, существует ли iOption в структуре.Конечно, SFINAE работает для имени функции или сигнатуры функции, но не уверен, что он работает для значения enum.

1 Ответ

6 голосов
/ 22 декабря 2011

Если вы можете использовать C ++ 11, это совершенно тривиально:

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

Версия C ++ 03 (на удивление) похожа:

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

Использование:

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
}
...