【问题标题】:How to create C++20 concept for typelist predicate?如何为类型列表谓词创建 C++20 概念?
【发布时间】:2019-09-01 19:21:16
【问题描述】:

我开始学习 C++20 的概念。我想为 typelist 的过滤谓词创建一个concept

假设,有一个这样定义的类型列表:

template <typename ...TYPE>
struct List {
};

还有Filter,它可以根据谓词过滤类型列表。一个可能的定义是这样的:

template <template <typename> typename PREDICATE, typename LIST>
struct Filter {
    using result = List<...>; // some implementation here
};

这意味着,对于每个LISTTYPE 参数,必须评估PREDICATE&lt;TYPE&gt;::value(它是一个bool 值),如果它是true,那么Filter::result 必须包含@987654332 @。

现在,我如何为PREDICATE 创建一个concept,所以Filter 将只接受它,如果它包含一个value 成员(对于所有TYPE 专业化,它在LIST 中) ?

我的意思是,对于这个MyPredicateconcept 应该只允许用LIST 实例化Filter,除了some_type1some_type2 之外没有其他类型:

template <typename TYPE>
struct MyPredicate;

template <>
struct MyPredicate<some_type1> {
    static constexpr bool value = true;
};

template <>
struct MyPredicate<some_type2> {
    static constexpr bool value = false;
};

Filter<MyPredicate, List<some_type1, some_type2>>::result x; // here, x should have the type List<some_type1>
Filter<MyPredicate, List<int>>::result y; // should not compile, as MyPredicate<int> isn't defined

【问题讨论】:

  • List 中是否只有一个元素评估为 true?
  • @0x499602D2:不,可以是任何东西
  • This answer 与您要查找的内容接近。

标签: c++ c++20


【解决方案1】:

你有一个检查单个实例化的概念:

template <typename T>
concept nested_value = std::same_as<decltype(T::value), bool>;

您可以在 fold-expression 中使用它:

template <template <typename> class Pred, typename List>
struct Filter;

template <template <typename> class Pred, template <typename...> class L, typename... Ts>
    requires (nested_value<Pred<Ts>> && ... )
struct Filter<Pred, L<Ts...>> {
    // ...
};

或者你基本上可以在一个概念中做同样的事情:

template <template <typename> class Pred, typename List>
struct all_nested_impl : std::false_type { };

template <template <typename> class Pred, template <typename...> class L, typename... Ts>
struct all_nested_impl<Pred, L<Ts...>>
    : std::bool_constant<(nested_value<Pred<Ts>> && ...)>
{ };

template <template <typename> class Pred, typename List>
concept all_nested = all_nested_impl<Pred, List>::value;

template <template <typename> class Pred, typename List>
    requires all_nested<Pred, List>
struct Filter;

或者如果你只是翻转参数,你就可以写:

template <template <typename> class Pred, all_nested<Pred> List>
struct Filter;

【讨论】:

  • 他想要一个List&lt;T...&gt;,其中包含给定List&lt;U...&gt;Predicate&lt;U&gt;::value 为真的所有元素。他想过滤掉所有不是的。
  • @0x499602D2 这不是问题要问的:“我怎样才能为 PREDICATE 创建一个概念,所以 Filter 只会接受它,如果它包含一个值成员(对于所有 TYPE 特化,即在 LIST 中)?”
  • @0x499602D2 是对的,我的意思是 valuebool 成员,而不是类型(参见我的示例),Filter 会将类型放入结果中,如果此 @987654331 @ 是 true。但我认为我可以修改你的答案,所以它的行为就像我想要的那样。很抱歉让您感到困惑(我明白了,您所说的“接受”与我的意思不同)。
  • @geza 嗯?如果 0x4 是对的,那么我的回答与问题无关。但是,概念也与问题无关。那么你真正想要的是什么?
  • 嗯。为什么概念与我的问题无关?我想有概念,所以我会得到更好的错误消息(它们不是过滤问题的强制性)。您的解决方案解决了问题,只是您使用 value 作为类型,而不是作为 bool 值。我轻松地修改了您的解决方案,它可以满足我的要求。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-27
  • 1970-01-01
  • 1970-01-01
  • 2023-01-10
  • 2020-09-28
  • 2021-07-12
  • 1970-01-01
相关资源
最近更新 更多