SFINAE用于类成员重载方法

时间:2015-02-04 12:31:11

标签: c++ templates member sfinae enable-if

请考虑以下代码段:

#include <type_traits>

struct UseMap;
struct NoMap;

template<typename MapType = NoMap>
class MyClass
{
public:

  typename std::enable_if<std::is_same<MapType, NoMap>::value, bool>::type
  handleEvent(int someVal)
  {
    return doSomething();
  }

  typename std::enable_if<std::is_same<MapType, UseMap>::value, bool>::type
  handleEvent(int someVal)
  {
    return doSomethingDifferent();
  }

  bool doSomething() {};
  bool doSomethingDifferent() {};
};

int main() {
  MyClass obj1();
  MyClass<UseMap> obj2();
  return 0;
}

是否可以只编译一个handleEvent方法,具体取决于提供的模板类类型? 通过上面的示例,编译器提供:

prog.cpp:18:3: error: 'typename std::enable_if<std::is_same<MapType, UseMap>::value, bool>::type MyClass<MapType>::handleEvent(int)' cannot be overloaded

2 个答案:

答案 0 :(得分:3)

我认为你必须制作重载的功能模板。

template<typename T = MapType,
  typename std::enable_if<
    std::is_same<T, NoMap>::value>::type *& = nullptr>
bool
handleEvent(int someVal)
{
  return doSomething();
}

template<typename T = MapType,
  typename std::enable_if<
    std::is_same<T, UseMap>::value>::type *& = nullptr>
bool
handleEvent(int someVal)
{
  return doSomethingDifferent();
}

这通过编译。 (clang-600.0.54 with -std=c++11

答案 1 :(得分:1)

找到答案的补充:你也可以从一个易于专门化的基类继承。

struct UseMap;
struct NoMap;

template<typename>
class MyClass;

namespace detail {
  // Container for the handleEvent() function
  template<typename>
  struct MyClassHandler;
}

// Enter CRTP !
template<typename MapType = NoMap>
class MyClass : detail::MyClassHandler<MyClass<MapType>>
{
    friend class detail::MyClassHandler<MyClass<MapType>>;
public:
  using detail::MyClassHandler<MyClass<MapType>>::handleEvent;

  bool doSomething() {};
  bool doSomethingDifferent() {};
};

// Actual specializations now that the full definition of MyClass is in scope
namespace detail {
  template<>
  struct MyClassHandler<MyClass<NoMap>> {
    bool handleEvent(int someVal)
    {
      return static_cast<MyClass<NoMap>*>(this)->doSomething();
    }
  };

  template<>
  struct MyClassHandler<MyClass<UseMap>> {
    bool handleEvent(int someVal)
    {
      return static_cast<MyClass<UseMap>*>(this)->doSomethingDifferent();
    }
  };
}

我觉得我过于复杂了声明顺序,请仔细检查:)