如何使用带有模板参数的成员函数模板为 class 编写 C++ 概念?
How to write a c++ concept for class with member function template that takes a template argument?
如何编写 C++ 20 概念,要求成员函数模板采用必须提供的模板参数?
以下概念的目标是检查类型是否类似于元组,除了检查 std::get<I>(t)
我想检查 t.get<I>()
.
以下不使用 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>;
};
如果在get
之前没有使用template
,当然编译不通过(没有尖括号,less/greater比运算符)。
要让它编译,你可以这样写:
template <typename E, int idx>
concept Tpl = requires(E const e)
{
{
e.template get<idx>()
} -> std::convertible_to<float>;
};
但请告诉我们您真正想要什么。
这个:
template <typename E>
concept Tpl = requires(E const e, int idx)
{
{
e.template get<idx>()
} -> std::convertible_to<float>;
};
不起作用,因为 idx
不是常量表达式,您需要它在调用 get
.
的上下文中是一个
为此,您需要选择索引的特定值以进行检查。您唯一可以真正选择的是 0
:
template <typename E>
concept Tpl = requires (E const e) {
{ e.template get<0>() } -> std::convertible_to<float>;
};
这可能会匹配函数模板 get
,该模板参数类型为 int*
或 nullptr_t
。如果这是一个问题,我们可以用更复杂的方式拼写 0
以避免它成为空指针常量,无论是简单的 1-1
还是将 [=22 类型的对象作为第二个“参数” =]:
template <typename E>
concept Tpl = requires (E const e, std::integral_constant<size_t, 0> value) {
{ e.template get<value()>() } -> std::convertible_to<float>;
};
如果最终目标是检查 e.get<I>()
是否适用于 所有 I
来自 [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>;
};
然后构建一个 Is...
的参数包,这样你最终构建一个像 (tuple_like_impl<E, Is> && ...)
.
这样的约束
但只有在确实需要时才应该采取这一步骤。
如何编写 C++ 20 概念,要求成员函数模板采用必须提供的模板参数?
以下概念的目标是检查类型是否类似于元组,除了检查 std::get<I>(t)
我想检查 t.get<I>()
.
以下不使用 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>;
};
如果在get
之前没有使用template
,当然编译不通过(没有尖括号,less/greater比运算符)。
要让它编译,你可以这样写:
template <typename E, int idx>
concept Tpl = requires(E const e)
{
{
e.template get<idx>()
} -> std::convertible_to<float>;
};
但请告诉我们您真正想要什么。
这个:
template <typename E>
concept Tpl = requires(E const e, int idx)
{
{
e.template get<idx>()
} -> std::convertible_to<float>;
};
不起作用,因为 idx
不是常量表达式,您需要它在调用 get
.
为此,您需要选择索引的特定值以进行检查。您唯一可以真正选择的是 0
:
template <typename E>
concept Tpl = requires (E const e) {
{ e.template get<0>() } -> std::convertible_to<float>;
};
这可能会匹配函数模板 get
,该模板参数类型为 int*
或 nullptr_t
。如果这是一个问题,我们可以用更复杂的方式拼写 0
以避免它成为空指针常量,无论是简单的 1-1
还是将 [=22 类型的对象作为第二个“参数” =]:
template <typename E>
concept Tpl = requires (E const e, std::integral_constant<size_t, 0> value) {
{ e.template get<value()>() } -> std::convertible_to<float>;
};
如果最终目标是检查 e.get<I>()
是否适用于 所有 I
来自 [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>;
};
然后构建一个 Is...
的参数包,这样你最终构建一个像 (tuple_like_impl<E, Is> && ...)
.
但只有在确实需要时才应该采取这一步骤。