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下一个问题是,你的概念总是会失败,因为你的set和reset函数不是const。由于非类型模板参数必须始终是编译时常量,因此您无法访问其上的非 const 成员函数。
这里给出了工作示例:
\ntemplate <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\nRun Code Online (Sandbox Code Playgroud)\n\n对于成员函数的问题const,我们可以采用以下技巧来解决该问题:
#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}\nRun Code Online (Sandbox Code Playgroud)\n\n
您的概念的语法不正确,这是一个工作示例。
#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)
由于概念约束非类型模板参数而不是类型,因此可以通过关键字将其指定为概念的模板参数来检查requires它
template <auto output> requires DigitalOutput<output>
struct driver { };
Run Code Online (Sandbox Code Playgroud)