如何为带有接受模板参数的成员函数模板的类编写 C++ 概念?

kor*_*kos 2 c++ templates member concept c++20

如何编写需要成员函数模板且必须提供模板参数的 C++ 20 概念?

以下概念的目标是检查类型是否类似于元组,除非std::get<I>(t)我想检查而不是检查t.get<I>()

以下内容不会使用 switch 与 g++ 10.1 一起编译-std=c++2a

#include <concepts>

template <typename E> 
concept Tpl = requires(E const e, int idx)
   {
      {
         e.template get<idx>()
      } -> std::convertible_to<float>;
   };
Run Code Online (Sandbox Code Playgroud)

如果template之前没有使用过get,它当然不会编译(没有尖括号,小于/大于运算符)。

Bar*_*rry 5

这:

template <typename E> 
concept Tpl = requires(E const e, int idx)
   {
      {
         e.template get<idx>()
      } -> std::convertible_to<float>;
   };
Run Code Online (Sandbox Code Playgroud)

不起作用,因为idx不是常量表达式,并且您需要它在调用 的上下文中成为常量表达式get

为此,您需要选择索引的特定值进行检查。您真正可以选择的唯一一个是0

template <typename E> 
concept Tpl = requires (E const e) {
    { e.template get<0>() } -> std::convertible_to<float>;
};
Run Code Online (Sandbox Code Playgroud)

get这可能会匹配具有类型int*或的模板参数的函数模板nullptr_t。如果这是一个问题,我们可以0用更复杂的方式拼写以避免它成为空指针常量,无论是简单的1-1还是将类型对象作为第二个“参数” integral_constant<size_t, 0>

template <typename E> 
concept Tpl = requires (E const e, std::integral_constant<size_t, 0> value) {
    { e.template get<value()>() } -> std::convertible_to<float>;
};
Run Code Online (Sandbox Code Playgroud)

如果最终的目标是检查是否e.get<I>()适用于所有 Ifrom [0, tuple_size_v<E>),那么您必须采取稍微不同的方法。在这种情况下,您将希望您正在检查的索引成为概念本身的一部分。如:

template <typename E, size_t I>
concept tuple_like_impl = requires (E const e) {
    { e.template get<I>() } -> std::convertible_to<float>;
};
Run Code Online (Sandbox Code Playgroud)

然后建立一个Is...这样的参数包,最终构造一个像 的约束(tuple_like_impl<E, Is> && ...)

但只有当您确实需要时才应该采取这一步骤。