C++ 概念:类型与多种类型中的任何一种相同?

Nic*_*asM 6 c++ c++-concepts c++20

我想定义一个概念,指示类型是几种受支持的类型之一。我可以通过重复列出类型来做到这一点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>;
Run Code Online (Sandbox Code Playgroud)

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

Nic*_*asM 12

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

template <typename T, typename... U>
concept IsAnyOf = (std::same_as<T, U> || ...);
Run Code Online (Sandbox Code Playgroud)

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

template <typename T>
concept IsMySupportedType = IsAnyOf<T, std::int32_t, std::int64_t, float, double>;
Run Code Online (Sandbox Code Playgroud)

T请注意,右侧的首字母很重要。

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

static_assert(IsMySupportedType<float>);
static_assert(!IsMySupportedType<std::int8_t>);
Run Code Online (Sandbox Code Playgroud)

编译示例: 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;` (3认同)

Ted*_*gmo 5

我会使用std::disjunction它的优点是它是短路的:
“如果有一个Bi带有 的模板类型参数bool(Bi::value) != false,那么实例化disjunction<B1, ..., BN>::value不需要Bj::valuefor的实例化j > 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>;
Run Code Online (Sandbox Code Playgroud)

演示

  • 概念机制是否可以“查看内部”`std::disjunction_v&lt;...&gt;` 以实现约束的部分排序?这就是我对“std::disjunction_v”的担忧。 (3认同)
  • 关于约束的部分排序的一点很好:使用折叠表达式,“IsAnyOf&lt;T, int, char, double&gt;”包含“IsAnyOf&lt;T, double, int&gt;”。使用 disjunction_v 时,any_of&lt;T, int, char, double&gt;` 不会包含 `any_of&lt;T, double, int&gt;`,因此这些约束的重载会变得不明确。 (3认同)