c++ 我如何实现逻辑或,以便在一个'requires'表达式中存在一个成员函数列表?

knpiaxh1  于 2023-03-25  发布在  其他
关注(0)|答案(2)|浏览(122)

我有一个泛型函数,它可以接受至少有一个成员函数列表的类型。
我正在尝试写一个内联的requires表达式来验证这一点。
我下面有一个例子,它无法编译,因为我的类型都没有传递 requires 子句

#include <iostream>

struct Foo
{
    bool has_foo() const { return true; }
};

struct Bar
{
    bool has_bar() const { return true; }
};

template<typename T>
bool check(const T& t)
    requires requires (T t)
    {
        { t.has_foo() || t.has_bar() };
    }
{
    if constexpr (requires { t.has_foo(); })
    {
        if (t.has_foo())
            std::cout << "has foo\n";
        else
            std::cout << "no foo\n";
    }
    if constexpr (requires { t.has_bar(); })
    {
        if (t.has_bar())
            std::cout << "has bar\n";
        else
            std::cout << "no bar\n";
    }
    return true;
}

int main()
{
    check(Foo());
    check(Bar());
    return 0;
}

由于以下原因,构建失败:

test.cpp:40:10: error: no matching function for call to 'check(Foo)'
   40 |     check(Foo());
      |     ~~~~~^~~~~~~
test.cpp:15:6: note: candidate: 'template<class T> bool check(const T&) requires requires(T t) {{t.has_foo() || t.has_bar()};}'
   15 | bool check(const T& t)
      |      ^~~~~
test.cpp:15:6: note:   template argument deduction/substitution failed:
test.cpp:15:6: note: constraints not satisfied
test.cpp: In substitution of 'template<class T> bool check(const T&) requires requires(T t) {{t.has_foo() || t.has_bar()};} [with T = Foo]':
test.cpp:40:10:   required from here
test.cpp:15:6:   required by the constraints of 'template<class T> bool check(const T&) requires requires(T t) {{t.has_foo() || t.has_bar()};}'
test.cpp:16:14:   in requirements with 'T t' [with T = Foo]
test.cpp:18:23: note: the required expression '(t.has_foo() || t.has_bar())' is invalid, because
   18 |         { t.has_foo() || t.has_bar() };
      |           ~~~~~~~~~~~~^~~~~~~~~~~~~~
test.cpp:18:28: error: 'struct Foo' has no member named 'has_bar'
   18 |         { t.has_foo() || t.has_bar() };
      |                          ~~^~~~~~~

我怎样才能把我的requires表达式

requires (T t)
{
    { t.has_foo() || t.has_bar() };
}

转换成逻辑或表达式,这样满足表达式中 * 任一 * 的类型都是允许的?

u4vypkhs

u4vypkhs1#

您可以将其拆分为两个requires表达式,它们可以与逻辑OR组合:

template<typename T>
bool check(const T& t)
    requires(
        requires (T t) { t.has_foo(); } ||
        requires (T t) { t.has_bar(); }
        )
{
    // [...]
}

如果这看起来太复杂,你也可以定义为一个新的概念:

template<typename T>
concept has_foo_or_bar =
    requires (T t) { t.has_foo(); } ||
    requires (T t) { t.has_bar(); };

template<typename T>
bool check(const T& t)
    requires( has_foo_or_bar<T>(t) )
{
    // [...]
}

Compiler Explorer

eit6fx6z

eit6fx6z2#

您可以编写两个不同的概念:

#include <iostream>
#include <concepts>

struct Foo
{
    bool foo() const { return true; }
};

struct Bar
{
    bool bar() const { return true; }
};

template<typename T>
concept has_foo = requires (T t)
{ { t.foo() } -> std::same_as<bool>; };

template<typename T>
concept has_bar = requires (T t)
{ { t.bar() } -> std::same_as<bool>; };

然后,您可以添加另一个概念:

template<typename T>
concept has_foo_or_bar = has_bar<T> or has_foo<T>;

或者分别使用它们:

template<typename T>
bool check(const T& t)
    requires  has_foo<T> or has_bar<T>
{
    if constexpr ( has_foo<T> )
    {
        // ...
    }
    if constexpr ( has_bar<T> )
    {
        //  ...
    }
    // ...
}

相关问题