【发布时间】:2018-11-28 06:38:15
【问题描述】:
我有许多EnableIf 特征,基本上检查输入类型是否满足接口。我试图创建一个通用的 Resolve 特征,可用于将它们转换为布尔特征。
类似这样的东西 - https://wandbox.org/permlink/ydEMyErOoaOa60Jx
template <
template <typename...> class Predicate,
typename T,
typename = std::void_t<>>
struct Resolve : std::false_type {};
template <template <typename...> class Predicate, typename T>
struct Resolve<Predicate, T, Predicate<T>> : std::true_type {};
现在如果你有这样的EnableIf trait
template <typename T>
using EnableIfHasFoo = std::void_t<decltype(std::declval<T>().foo())>;
您可以非常快速地创建一个布尔版本
template <typename T>
struct HasFoo : Resolve<EnableIfHasFoo, T> {};
或者类似的变量模板。
但由于某种原因,部分专业化没有按预期工作。解决无法按预期工作。在此处查看输出 - https://wandbox.org/permlink/ydEMyErOoaOa60Jx。 “手动”实现的相同功能 - https://wandbox.org/permlink/fmcFT3kLSqyiBprm
我正在求助于自己手动定义类型。是否有我遗漏的部分特化和模板模板参数的细节?
【问题讨论】:
-
我找不到原因,但您需要部分专业化为
Resolve<Predicate, T, std::void_t<Predicate<T>>。那么此时也可以去掉别名中的std::void_t。 -
顺便说一句,你的代码看起来很像dectection idiom
-
@GuillaumeRacicot 但是谓词是什么?只是 decltype()?很不错!此外,令人困惑的是为什么上述方法不起作用。
-
它可以是一个别名模板来简单地
decltype。我不知道为什么,但void_t必须是部分专业化的。我认为这与部分排序的工作方式有关。
标签: c++ templates c++17 sfinae enable-if