通过枚举重载模板化成员函数
Overloading a templated member function through enum
假设我有一个 EventHandle
class,它由 READ
、WRITE
和 SIGNAL
唯一枚举,并且我正在实现一个成员模板对于不同的枚举,它应该 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); }
假设我有一个 EventHandle
class,它由 READ
、WRITE
和 SIGNAL
唯一枚举,并且我正在实现一个成员模板对于不同的枚举,它应该 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
.
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); }