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

Overloading a templated member function through enum

本文关键字:成员 函数 枚举 重载      更新时间:2023-10-16

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

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派生的类。

class ReadEventHandle : public EventHandle {...}
class WriteEventHandle : public EventHandle {...}
class SignalEventHandle : public EventHandle {...}

很明显,我写的东西无法编译。有没有任何方法可以在"编译"时实现这种类型的强制转换重载(例如,枚举上没有开关)?

一种具有某些特征和专业化的替代品:

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

演示

我不能说我完全理解你想做什么,但你肯定没有正确使用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
}