【问题标题】:C++ concept that a type is same_as any one of several types?类型与几种类型中的任何一种相同的C ++概念?
【发布时间】:2022-08-19 09:28:13
【问题描述】:

我想定义一个概念,表明一种类型是几种支持的类型之一。我可以通过使用std::same_as<T, U> 重复列出类型来做到这一点:

#include <concepts>

template <typename T>
concept IsMySupportedType = std::same_as<T, int32_t> || std::same_as<T, int64_t> || std::same_as<T, float> || std::same_as<T, double>;

有没有更简洁的方法来写这个而不重复 std::same_as 概念?

    标签: c++ c++20 c++-concepts


    【解决方案1】:

    这可以使用可变辅助概念(取自 std::same_as 的 cppreference)来完成:

    template <typename T, typename... U>
    concept IsAnyOf = (std::same_as<T, U> || ...);
    

    这可用于定义所需的概念,如下所示:

    template <typename T>
    concept IsMySupportedType = IsAnyOf<T, std::int32_t, std::int64_t, float, double>;
    

    请注意,右侧的初始T 很重要。

    由此产生的概念可以按预期使用:

    static_assert(IsMySupportedType<float>);
    static_assert(!IsMySupportedType<std::int8_t>);
    

    编译示例:https://godbolt.org/z/6dE9r1EY6

    【讨论】:

    • 仅当概念名称或概念模板 ID 用作声明的约束类型时,才会自动添加初始 T,如 void f(IsAnyOf&lt;char, float, double&gt; value);template &lt;IsAnyOf&lt;char, float, double&gt; T&gt;
    • "在我看来,右侧的初始 T 应该是隐含的,而不是必需的" 嗯...为什么?你没有在一个类型已经存在的地方使用它(例如requires 表达式中的-&gt; 符号)。
    • @aschepler,Nicol Bolas,感谢您澄清这不是隐式使用类型参数的正确上下文。
    • 我猜还有IsAnyOf&lt;char, float, double&gt; auto var = 0.0;,它并没有完全代替类型,而是与声明有关。
    【解决方案2】:

    我会使用std::disjunction,它的好处是短路:
    “如果有一个模板类型参数Bibool(Bi::value) != false,那么实例化disjunction&lt;B1, ..., BN&gt;::value 不需要为Bj::value 实例化j &gt; i

    template <class T, class... U>
    concept any_of = std::disjunction_v<std::is_same<T, U>...>;
    
    template <class T>
    concept IsMySupportedType = any_of<T, std::int32_t, std::int64_t, float, double>;
    

    Demo

    【讨论】:

    • 我了解std::disjunction 的一般好处,但它在这里有什么用处吗?即使TU 不完整,std::is_same&lt;T, U&gt;::value 也不会实例化失败。
    • 概念机器是否可以“查看内部”std::disjunction_v&lt;...&gt; 以对约束进行部分排序?这将是我对std::disjunction_v 的担忧。
    • @aschepler 并不是说​​它会失败,而是如果找到匹配项,它甚至不会实例化 is_sames 的其余部分。
    • @NicholasM 我不确定我是否理解。它将按照您提供参数U... 的顺序实例化is_sames,但它不会实例化比需要更多的is_sames。
    • 关于约束的部分排序这一点很好:使用折叠表达式,IsAnyOf&lt;T, int, char, double&gt; 包含IsAnyOf&lt;T, double, int&gt;。使用disjunction_vany_of&lt;T, int, char, double&gt; 不包含any_of&lt;T, double, int&gt;,因此这些约束的重载将变得模棱两可。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 2021-10-12
    • 2019-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多