概念:检查带有参数的方法的签名
Concepts: checking signatures of methods with arguments
我一直在研究概念。这是一个最小的例子,我试图根据方法签名创建一个概念:
template<typename T>
concept bool myConcept() {
return requires(T a, int i) {
{ a.foo() } -> int;
{ a.bar(i) } -> int;
};
}
struct Object {
int foo() {return 0;}
int bar(int) {return 0;}
};
static_assert(myConcept<Object>(), "Object does not adhere to myConcept");
令我惊讶的是,写 { a.bar(int) } -> int
并没有奏效,所以我求助于向 requires
表达式添加一个额外的参数。这看起来有点奇怪,我想知道是否有办法做同样的事情。另一件有用的事情是使用类似 { a.bar((int)0) } -> int
的东西,但我发现这更糟。
概念检查表达式,a.bar(int)
不是一个。通过写作
{ a.foo(int) } -> int
您要求编译器检查上述表达式的类型是否为 int
。这没有意义。
您确实找到了有效的替代方案;另一个可能是,因为 a.bar(x)
的类型不依赖于 x
' 值:
template<typename T>
concept bool myConcept() {
return requires(T a) {
{ a.foo() } -> int;
{ a.bar(0) } -> int;
};
}
struct Object {
int foo() {return 0;}
int bar(int) {return 0;}
};
static_assert(myConcept<Object>(), "Object does not adhere to myConcept");
由于类型的实际值无关紧要,我建议使用 int{}
作为参数。这记录了争论的目的,IMO:
{ a.bar(int{}) } -> int;
显然这不适用于没有默认构造函数的类型。在模板中,人们会使用 std::declval
来解决类似的问题,但这里 GCC 错误:
error: static assertion failed: declval() must not be used!
但是没有什么可以阻止我们编写与概念一起使用的等效(但未实现)函数,如下所示:
#include <type_traits>
template <class T>
typename std::add_rvalue_reference<T>::type makeval();
template<typename T>
concept bool myConcept() {
return requires(T a, int i) {
{ a.foo() } -> int;
{ a.bar(makeval<int>()) } -> int;
};
}
struct Object {
int foo() {return 0;}
int bar(int) {return 0;}
};
static_assert(myConcept<Object>(), "Object does not adhere to myConcept");
我一直在研究概念。这是一个最小的例子,我试图根据方法签名创建一个概念:
template<typename T>
concept bool myConcept() {
return requires(T a, int i) {
{ a.foo() } -> int;
{ a.bar(i) } -> int;
};
}
struct Object {
int foo() {return 0;}
int bar(int) {return 0;}
};
static_assert(myConcept<Object>(), "Object does not adhere to myConcept");
令我惊讶的是,写 { a.bar(int) } -> int
并没有奏效,所以我求助于向 requires
表达式添加一个额外的参数。这看起来有点奇怪,我想知道是否有办法做同样的事情。另一件有用的事情是使用类似 { a.bar((int)0) } -> int
的东西,但我发现这更糟。
概念检查表达式,a.bar(int)
不是一个。通过写作
{ a.foo(int) } -> int
您要求编译器检查上述表达式的类型是否为 int
。这没有意义。
您确实找到了有效的替代方案;另一个可能是,因为 a.bar(x)
的类型不依赖于 x
' 值:
template<typename T>
concept bool myConcept() {
return requires(T a) {
{ a.foo() } -> int;
{ a.bar(0) } -> int;
};
}
struct Object {
int foo() {return 0;}
int bar(int) {return 0;}
};
static_assert(myConcept<Object>(), "Object does not adhere to myConcept");
由于类型的实际值无关紧要,我建议使用 int{}
作为参数。这记录了争论的目的,IMO:
{ a.bar(int{}) } -> int;
显然这不适用于没有默认构造函数的类型。在模板中,人们会使用 std::declval
来解决类似的问题,但这里 GCC 错误:
error: static assertion failed: declval() must not be used!
但是没有什么可以阻止我们编写与概念一起使用的等效(但未实现)函数,如下所示:
#include <type_traits>
template <class T>
typename std::add_rvalue_reference<T>::type makeval();
template<typename T>
concept bool myConcept() {
return requires(T a, int i) {
{ a.foo() } -> int;
{ a.bar(makeval<int>()) } -> int;
};
}
struct Object {
int foo() {return 0;}
int bar(int) {return 0;}
};
static_assert(myConcept<Object>(), "Object does not adhere to myConcept");