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 代码变得更加容易,而无需大惊小怪)。