如何在单个概念中对需求进行逻辑“或”?

问题描述 投票:0回答:3

我有以下案例


template<typename Class>
concept has_member = requires (Class t)
{ 
    // How can I write only if either of the following conditions is satisfied?
    {t.isInterface() }->std::same_as<bool>;
    // or
    {t.canInterface() }->std::same_as<bool>;
    // or
    // ... more conditions!
};

struct A {
    bool isInterface() const { return true; }
};

struct B {
    bool canInterface() const { return true; }
};

void foo(const has_member auto& A_or_B)
{
    // do something
}

int main()
{
    foo(A{}); // should work
    foo(B{}); // should work
}

正如我在代码注释中提到的,我想从逻辑上或要求(在单个

concepts
中),以便类
A
B
可以传递给
doSomething()

据我所知,目前的概念是检查所有需求,这意味着逻辑与。 如果我把它拆成不同的概念,一切都会起作用,但我需要编写更多的概念来满足意图。

可以合二为一吗?类似伪代码的东西

template<typename Class>
concept has_member = requires (Class t)
{ 
    {t.isInterface() }->std::same_as<bool>  ||  {t.canInterface() }->std::same_as<bool>;
    // ... 
};
c++ templates c++20 c++-concepts function-templates
3个回答
4
投票

可以合二为一吗?

是的,这是可能的。您可以将两个

requires
的合取写成如下:

template<typename Class>
concept has_member = 
    requires (Class t) { {t.isInterface() }->std::same_as<bool>; }
    || //---> like this
    requires (Class t) { {t.canInterface() }->std::same_as<bool>;};
// ... more conditions!

演示


4
投票

任何时候你想开始构建概念,你都应该从使用点开始。也就是说,您将出于某种目的使用一些模板参数的地方。

这意味着,您从

foo

 开始。 
foo
 如何使用此界面“做某事”?它不可能这么简单:

void foo(const has_member auto& A_or_B) { A_or_B.isInterface(); }
对于某些 

has_member

 对象来说,这将是一个编译错误。所以你需要这样做:

void foo(const has_member auto& A_or_B) { if constexpr(<stuff>) A_or_B.isInterface(); else A_or_B.hasInterface(); }
其中 

<stuff>

 是一些编译时条件检查,以查看对象具有哪个实际接口。您可以拼出 
requires
 子句,但这会不必要地冗长。所以只需将它们固定在一个概念中即可:

template<typename T> concept has_is_interface = requires (Class t) { {t.isInterface() }->std::same_as<bool>; }; template<typename T> concept has_can_interface = requires (Class t) { {t.canInterface() }->std::same_as<bool>; };
现在,你的问题已经有了答案:

template<typename Class> concept has_member = (has_is_interface || has_can_interface) && requires (Class t) { // ... more conditions! };


话虽如此,这种设计通常是错误的。原因是它在使用时写了很多冗长的内容。

可能想要的是一些可以调用适当的成员接口的免费函数:

bool do_is_interface(has_is_interface auto const& is_if) { return is_if.is_interface(); } bool do_is_interface(has_can_interface auto const& is_if) { return is_if.can_interface(); }
然后你的概念看起来像:

template<typename Class> concept has_member = requires (Class t) { { do_is_interface(t) } -> std::same_as<bool> // ... more conditions! };
    

3
投票
您可以使用以下概念形式

从标准中窃取

#include <concepts> template<typename Class> concept has_member = requires (Class t) { requires (requires { { t.isInterface() } -> std::same_as<bool>; } || requires { { t.canInterface() } -> std::same_as<bool>; } // add more functions ); };
这允许我们直接在 

requires

 子句中添加不同的成员函数。

© www.soinside.com 2019 - 2024. All rights reserved.