如何根据模板参数是否具有别名来专门化类型
How to specialize a type based on whether a template parameter has an alias
例如,我希望能够根据容器是否具有指定的 typedef 来专门化类型
class SomethingElse {};
class Something {
using Type = int;
};
static constexpr bool value = ChooseIfType<Something>::value;
当类型没有 typedef Type
时,有没有办法让 ChooseIfType
变为 return false?
我觉得有一种简单的方法可以做到这一点,但我想不通。
谢谢!
只需使用 std::void_t
(或 C++11 替代方案):
template<typename T, typename = std::void_t<>>
struct ChooseIfType : std::false_type {};
template<typename T>
struct ChooseIfType<T, std::void_t<typename T::Type>> : std::true_type {};
该解决方案使用了 SFINAE。默认值永远不会畸形并创建值为 false 的特征。编译器尝试匹配所有模板特化(在本例中只有一个)。如果 T
具有成员类型 Type
,则 ChooseIfType<T, void_t<typename T::Type>>
比 ChooseIfType<T, void_t<>>
更专业。如果没有,那么它不是一个可行的专业化并且选择了默认值,但是替换失败不是错误。
根据 cppreference,C++11 void_t
实现可能如下所示:
template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;
例如,我希望能够根据容器是否具有指定的 typedef 来专门化类型
class SomethingElse {};
class Something {
using Type = int;
};
static constexpr bool value = ChooseIfType<Something>::value;
当类型没有 typedef Type
时,有没有办法让 ChooseIfType
变为 return false?
我觉得有一种简单的方法可以做到这一点,但我想不通。
谢谢!
只需使用 std::void_t
(或 C++11 替代方案):
template<typename T, typename = std::void_t<>>
struct ChooseIfType : std::false_type {};
template<typename T>
struct ChooseIfType<T, std::void_t<typename T::Type>> : std::true_type {};
该解决方案使用了 SFINAE。默认值永远不会畸形并创建值为 false 的特征。编译器尝试匹配所有模板特化(在本例中只有一个)。如果 T
具有成员类型 Type
,则 ChooseIfType<T, void_t<typename T::Type>>
比 ChooseIfType<T, void_t<>>
更专业。如果没有,那么它不是一个可行的专业化并且选择了默认值,但是替换失败不是错误。
根据 cppreference,C++11 void_t
实现可能如下所示:
template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;