C++ 概念 - 我可以有一个约束要求函数出现在 class 中吗?
C++ Concepts - Can I have a constraint requiring a function be present in a class?
我在下面有一个简单的代码片段,它使用编译:
g++-9 -std=c++2a -fconcepts
这是试图定义一个需要存在函数的概念。我希望输出为 "yes" 但它不是......知道为什么吗?谢谢
#include <iostream>
template <typename T>
concept bool HasFunc1 =
requires(T) {
{ T::func1() } -> int;
};
struct Test
{
int func1()
{
return 5;
}
};
int main()
{
if constexpr (HasFunc1<Test>)
std::cout << "yes\n";
}
您正在测试是否存在静态成员函数。你要的是
template <typename T>
concept bool HasFunc1 =
requires(T t) {
{ t.func1() } -> int;
};
尝试自己调用它:
Test::func1();
prog.cc: In function 'int main()':
prog.cc:19:14: error: cannot call member function 'int Test::func1()' without object
19 | Test::func1();
| ^
哦,对了。 func1
应该是一个 static
成员函数,或者你应该在你的概念中的一个实例上调用它:
template <typename T>
concept bool HasFunc1 =
requires(T t) {
{ t.func1() } -> int;
};
可以运行在编译时进行概念检查。
(OP 的检查仅在 运行 时评估。)
首先,准备一个检查函数(技术上是一个模板变量):
template <HasFunc1 h>
constexpr bool HasFunc1_satisfied = true;
然后在某处进行检查。
// The class to be tested
struct Test
{
int func1()
{
return 5;
}
};
// Do the test at the compile time
static_assert(HasFunc1_satisfied< Test >);
@makogan 问(埋在评论深处的 19):如果 func 有参数怎么办?
答案是:对于简单的情况,使用构造函数或 new 表达式来制造参数。 (不是特别可读,但比下面给出的可能正确的方式更具可读性)。
template <typename T>
concept HasFunc1 =
requires(T t) {
{ t.func1( int() ) } -> std::same_as<int>;
};
对于更复杂的示例,您可以在 requires 子句参数列表中声明测试参数:
concept IsCoServiceImplementation = requires(
T t,
CoServiceReply<typename T::return_type> *completionCallback)
{
{ T::return_type };
{t.OnSuspend(completionCallback) };
{t.OnCancel(completionCallback) };
};
这个概念确实有预期的意图(对我来说):它主要 将关于未能满足模板合同的嵌套 10 层错误消息转换为 几乎 条可读first-level 条错误消息。
所需代码和概念之间仍然存在奇怪的脱节。如果对参数类型有更严格的限制,那就太好了。测试 const-ness 非常困难。与我所希望的功能相去甚远。 :-(
我还在为 C++20 的特性而苦恼。我乐于接受有关如何做得更好的建议。
(CoService,如果您想知道的话,是我正在努力的一项实验性尝试,目的是使将协程代码编组回 non-coroutine 代码变得更加容易,而无需大惊小怪)。
我在下面有一个简单的代码片段,它使用编译:
g++-9 -std=c++2a -fconcepts
这是试图定义一个需要存在函数的概念。我希望输出为 "yes" 但它不是......知道为什么吗?谢谢
#include <iostream>
template <typename T>
concept bool HasFunc1 =
requires(T) {
{ T::func1() } -> int;
};
struct Test
{
int func1()
{
return 5;
}
};
int main()
{
if constexpr (HasFunc1<Test>)
std::cout << "yes\n";
}
您正在测试是否存在静态成员函数。你要的是
template <typename T>
concept bool HasFunc1 =
requires(T t) {
{ t.func1() } -> int;
};
尝试自己调用它:
Test::func1();
prog.cc: In function 'int main()':
prog.cc:19:14: error: cannot call member function 'int Test::func1()' without object
19 | Test::func1();
| ^
哦,对了。 func1
应该是一个 static
成员函数,或者你应该在你的概念中的一个实例上调用它:
template <typename T>
concept bool HasFunc1 =
requires(T t) {
{ t.func1() } -> int;
};
可以运行在编译时进行概念检查。 (OP 的检查仅在 运行 时评估。)
首先,准备一个检查函数(技术上是一个模板变量):
template <HasFunc1 h>
constexpr bool HasFunc1_satisfied = true;
然后在某处进行检查。
// The class to be tested
struct Test
{
int func1()
{
return 5;
}
};
// Do the test at the compile time
static_assert(HasFunc1_satisfied< Test >);
@makogan 问(埋在评论深处的 19):如果 func 有参数怎么办?
答案是:对于简单的情况,使用构造函数或 new 表达式来制造参数。 (不是特别可读,但比下面给出的可能正确的方式更具可读性)。
template <typename T>
concept HasFunc1 =
requires(T t) {
{ t.func1( int() ) } -> std::same_as<int>;
};
对于更复杂的示例,您可以在 requires 子句参数列表中声明测试参数:
concept IsCoServiceImplementation = requires(
T t,
CoServiceReply<typename T::return_type> *completionCallback)
{
{ T::return_type };
{t.OnSuspend(completionCallback) };
{t.OnCancel(completionCallback) };
};
这个概念确实有预期的意图(对我来说):它主要 将关于未能满足模板合同的嵌套 10 层错误消息转换为 几乎 条可读first-level 条错误消息。
所需代码和概念之间仍然存在奇怪的脱节。如果对参数类型有更严格的限制,那就太好了。测试 const-ness 非常困难。与我所希望的功能相去甚远。 :-(
我还在为 C++20 的特性而苦恼。我乐于接受有关如何做得更好的建议。
(CoService,如果您想知道的话,是我正在努力的一项实验性尝试,目的是使将协程代码编组回 non-coroutine 代码变得更加容易,而无需大惊小怪)。