C++20 使用概念来限制“自动”非类型模板参数?

Ste*_*fan 12 c++ templates c++-concepts c++20

我有一个模板类,它采用几个非类型参数(GPIO 描述符)。Auto 用于允许使用多种不同的 GPIO 实现。这些实现不能从公共基类派生。

我可以使用一个概念将这些参数限制为具有正确接口的参数吗?

我有一个概念,但它不起作用,GCC 告诉我“错误:‘DigitalOutput’不限制类型”:

template <auto gp>
concept DigitalOutput = requires() { gp.set(); gp.reset(); };

// template <auto output>
template <DigitalOutput output>
struct driver {...};
Run Code Online (Sandbox Code Playgroud)

有可能使这项工作成功吗?

Kla*_*aus 14

有2个问题:

\n

首先,您使用了错误的语法,这已经在 \xe5\xba\xb7\xe6\xa1\x93\xe7\x91\x8b 的答案中进行了解释。

\n

下一个问题是,你的概念总是会失败,因为你的setreset函数不是const。由于非类型模板参数必须始终是编译时常量,因此您无法访问其上的非 const 成员函数。

\n

这里给出了工作示例:

\n
template <auto gp>\nconcept DigitalOutput = requires()\n{\n    gp.set();\n    gp.reset();\n};\n\n\ntemplate <auto output> requires DigitalOutput<output>\nstruct driver\n{\n};\n\nstruct A\n{\n    void set() const {}     // must be const!\n    void reset() const {}    // must be const!\n};\n\nstruct B\n{\n};\n\n\nint main()\n{\n\n    A a;\n    driver<a> da;\n\n    B b;\n    driver<b> db; // fails as expected\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n

工作示例

\n

对于成员函数的问题const,我们可以采用以下技巧来解决该问题:

\n
#include <utility>\n#include <type_traits>\n\n    template <auto gp> \nconcept DigitalOutput = requires() \n{\n    // create a new value which is not const from the given non type template parm:\n    std::remove_const_t<decltype(gp)>().set();\n    std::remove_const_t<decltype(gp)>().reset(); \n};\n\n\ntemplate <auto output> requires DigitalOutput<output>\nstruct driver \n{\n};\n\nstruct A\n{\n    void set() {}    \n    void reset() {}\n};\n\nstruct B\n{\n};\n\n\nint main()\n{\n\n    A a;\n    driver<a> da; \n\n    B b;\n    driver<b> db;  // fails as expected\n}\n
Run Code Online (Sandbox Code Playgroud)\n

工作示例

\n

  • “*但我们可以解决这个问题...*”可以简化为 [`auto(gp).set();` 在 C++23 中](https://godbolt.org/z/qYeneP1Mz)。 (3认同)
  • @康桓伟 对于某些嵌入式平台来说,不依赖库可能是一个好点,好点!“不工作”对我来说是“requires( auto(gp) gp )”的意思。与 C++23 的所有新内容进行有趣的讨论... (2认同)

P K*_*mer 7

您的概念的语法不正确,这是一个工作示例。

#include <cstdint>
#include <concepts>

template <typename gp_t>
concept DigitalOutput = requires(gp_t gp) 
{ 
    gp.set(); 
    gp.reset(); 
};


struct output_t
{
    void set() {};
    void reset() {};
};

struct not_output_t
{
};

void fn(DigitalOutput auto output)
{

}


int main()
{
    output_t output;
    not_output_t not_output;

    fn(output);
    // fn(not_output); does not compile

    return 0;
}
Run Code Online (Sandbox Code Playgroud)


康桓瑋*_*康桓瑋 5

由于概念约束非类型模板参数而不是类型,因此可以通过关键字将其指定为概念的模板参数来检查requires

template <auto output> requires DigitalOutput<output>
struct driver { };
Run Code Online (Sandbox Code Playgroud)