通过枚举重载模板化成员函数

Overloading a templated member function through enum

假设我有一个 EventHandle class,它由 READWRITESIGNAL 唯一枚举,并且我正在实现一个成员模板对于不同的枚举,它应该 return 不同的数据类型。

enum class EventType {
  READ,
  WRITE,
  SIGNAL
};

class EventHandle {

public:

  template <EventType type, typename = enable_if_t<is_same<type, READ>::value>>
  ReadEventHandle* cast () { return static_cast<ReadEventHandle>(this); }

  template <EventType type, typename = enable_if_t<is_same<type, WRITE>::value>>
  WriteEventHandle* cast () { return static_cast<WriteEventHandle>(this); }

  template <EventType type, typename = enable_if_t<is_same<type, SIGNAL>::value>>
  SignalEventHandle* cast () { return static_cast<SignalEventHandle>(this); }
};

我从 EventHandle.

派生了三个 classes
class ReadEventHandle : public EventHandle {...}
class WriteEventHandle : public EventHandle {...}
class SignalEventHandle : public EventHandle {...}

显然我写的不能编译。有什么方法可以在 "compile" 时间实现这种类型转换重载(例如,不打开枚举)?

我不能说我完全理解你想要做什么,但你肯定没有正确使用 SFINAE。这是我希望可以作为指导的可编译代码:

#include <type_traits>

enum class EventType {
  READ,
  WRITE,
  SIGNAL
};

class ReadEventHandle { };
class WriteEventHandle { };
class SignalEventHandle { };

ReadEventHandle re;
WriteEventHandle we;
SignalEventHandle se;

class EventHandle {

public:

  template <EventType type,  std::enable_if_t<type == EventType::READ>* = nullptr >
  ReadEventHandle* cast () { return &re; }

  template <EventType type, std::enable_if_t<type == EventType::WRITE>* = nullptr >
  WriteEventHandle* cast () { return &we; }

  template <EventType type, std::enable_if_t<type == EventType::SIGNAL>* = nullptr>
  SignalEventHandle* cast () { return &se; }
};

void* check() {
  return EventHandle().cast<EventType::READ>(); // Depending on cast argument, different pointers returned
}

具有某些特征和专业化的替代方案:

enum class EventType {
  READ,
  WRITE,
  SIGNAL
};

class ReadEventHandle;
class WriteEventHandle;
class SignalEventHandle;

template <EventType E> struct EventHandleType;

template <> struct EventHandleType<EventType::READ> { using type = ReadEventHandle; };
template <> struct EventHandleType<EventType::WRITE> { using type = WriteEventHandle; };
template <> struct EventHandleType<EventType::SIGNAL> { using type = SignalEventHandle; };

然后:

class EventHandle {
public:

  template <EventType E>
  typename EventHandleType<E>::type* cast();
};

template <EventType E>
typename EventHandleType<E>::type*
EventHandle::cast() { return static_cast<typename EventHandleType<E>::type*>(this); }

Demo