C++:如何组合多个概念?

时间:2021-02-02 14:29:55

标签: c++ composition c++20 c++-concepts

这个标题似乎受到了很多批评。但是,我发现这个概念很难搜索。它在 C++ 领域也相对较新,学校仍在教授 C++11

避免XY问题的动机和背景

现在,我正在使用 concepts 检测嵌入式设备项目,作为逆向工程(和学习)过程的一部分。设备库和设备 API 的问题在于有各种各样的编程禁忌,这些禁忌源于文字设备(或设备产品线)功能:

  • 硬编码设置
  • 扩展
  • 设备功能的特定捆绑包或子集
  • 利用宏和辅助类来构建结构(structs building structs)
  • 没有简单的假设:跨平台和设备测试的大量错误处理包

代码最终 - 无论开发人员如何努力,我知道不可能有更好的结果 - 非常冗长和复杂。换句话说,它在功能上很简单,但很难理解。

通常,我可能会形成 structs 来包装捆绑包并隐藏硬编码内容,但现在我使用 concepts 因为它们允许我构建 my 接口命名空间我(一个单独的开发人员)可以更有效地更改或更新知识。我对使用设备的了解越少越好。

借助概念,我还可以保护我编写的代码,这些代码取决于我的概念化内容,以免设备制造商和 API 提供商传播更改。


在利用这些概念时,我试图尽早选择如何构建我的代码。

为了做出决定,我需要知道是否可以将 concepts 原子地写入,然后组合成 conceptual structures。例如:

// real code

// Concepts

template < typename ContextInfo>
concept ExtensibleDeviceContext = requires(ContextInfo & contextInfo, const char * name, 
                                           bool optional, void * devFeatures)
{
    { contextInfo.addDeviceExtension(name, optional, devFeatures)};
};

template< typename ContextInfo>
concept ExtensibleInstanceContext = requires(ContextInfo & contextInfo, const char * name, 
                                             bool optional)
{
  { contextInfo.addInstanceLayer(name, optional) };
  { contextInfo.addInstanceExtension(name, optional) };
};

// Some dummy functions

template<ExtensibleDeviceContext Cx>
void foo(Cx &context, const char *name, bool optional, void *devFeatures)
{
   context.addDeviceExtension(name, optional, devFeatures, version);
   context.addDeviceExtension(FOO_MACRO_1);
}

template<ExtensibleInstanceContext Cx>
void bar(Cx &context, const char *name, bool optional)
{
   context.addInstanceLayer(name, optional);
   context.addInstanceExtension(BAR_MACRO);
}

而我想要做的是,本质上,将概念组合成模板上下文“<...>”中的一组概念:

// psuedo-code: what I am trying to achieve

template<typename PortInfo: {ExtensibleInstanceContext, ExtensibleDeviceContext}>
void foobar(
      PortInfo port, 
      const char *portName, 
      bool optional, 
      const char *devName, 
      bool devOptional, 
      void *devFeatures
    )
{
   foo(port, devName, devOptional, devFeatures);
   bar(port, portName, optional);
};

这种concept组合可能吗?如果是这样,是否可以在上面概述的模板语法中做到这一点?如果没有,是否有一些“更好”或“预期”的方式来代替?

1 个答案:

答案 0 :(得分:3)

您可以使用 foobar 子句约束 requires,或命名您想要的概念的连词。

template<typename PortInfo>
requires ExtensibleInstanceContext<PortInfo> && ExtensibleDeviceContext<PortInfo>
void foobar(
      PortInfo port, 
      const char *portName, 
      bool optional, 
      const char *devName, 
      bool devOptional, 
      void *devFeatures
    )
{
   foo(port, devName, devOptional, devFeatures);
   bar(port, portName, optional);
};

template <typename ContextInfo>
concept ExtensibleDeviceInstanceContext = ExtensibleInstanceContext<ContextInfo> && ExtensibleDeviceContext<ContextInfo>;

template <ExtensibleDeviceInstanceContext PortInfo>
void foobar(
      PortInfo port, 
      const char *portName, 
      bool optional, 
      const char *devName, 
      bool devOptional, 
      void *devFeatures
    )
{
   foo(port, devName, devOptional, devFeatures);
   bar(port, portName, optional);
};

您可以使用 &&||! 及其通常的布尔含义来组合概念。