我有一个具有某些类型成员的类模板。此类型是根据实例化模板时提供的类型确定的。除非该类提供覆盖,否则它将使用默认值(在下面的示例中为双精度)。用作模板类型的类可以提供此覆盖[{'month': 'March', 'surname': 'john March'}, {'month': 'April', 'surname': "April O'Neil"}, {'month': 'May', 'surname': 'David May'}]
(此处“ Two”提供覆盖类型“ int”)。如果类提供了覆盖,则仅当该类还设置UseOverride标志时才应使用覆盖。如果标志不存在或为false,则应使用默认的“ double”。
问题是,如果模板类型不提供“类型”,则编译器在以下代码中给出错误。我怀疑我需要在这里使用SFINAE,但即使在整个下午的大部分时间里困惑并浏览了相关问题之后,仍无法找到合适的方法。
如何定义EventType模板以使其按预期工作?我想保留type
语法。
EventType<T>
答案 0 :(得分:2)
我不想让编译器抱怨“ type”在这里不可用(因为无论如何它都应该默认为double,因为该类指示不要使用覆盖)。但是编译器确实会产生错误。如何避免这种情况?
只需使用下面的type_identity
助手来延迟对::type
的访问:
template <typename T>
struct type_identity { using type = T; };
template <typename T>
using EventType = typename std::conditional_t<Override<T>()
, T
, type_identity<double>>::type;
// ~~~~~~~~~~~~^
答案 1 :(得分:1)
您处在正确的轨道上,但无需单独检查useOverride
和type
是否存在。相反,您可以在同一sfinae类中进行两项检查:
template <typename T, typename = void, typename = void>
struct EventType_T {
using t = double; // default if useOverride or type doesn't exist
};
template <typename T>
struct EventType_T<T, std::void_t<decltype(T::UseOverride)>,
std::void_t<typename T::type>> {
// choose type if useOverride is true, and double otherwise
using t = std::conditional_t<T::UseOverride, typename T::type, double>;
};
template <typename T>
using EventType = typename EventType_T<T>::t;
这里是demo。这样一来,您仍然可以像以前一样使用EventType<T>
语法。
请注意,t
成员而不是type
是非常规的,但是由于我们已经在type
中测试了一个T
成员,因此可能会更加清楚上。一旦您了解解决方案的工作原理,我建议使用type
。