C++:如何组合多个概念?
C++: How do I compose multiple concepts?
这个标题似乎受到了很多批评。但是,我发现这个概念很难搜索。它在 C++ 领域也相对较新,学校仍在教授 C++11
。
避免XY-Problem
的动机和背景
现在,作为逆向工程(和学习)过程的一部分,我正在使用 concepts
检测一个嵌入式设备项目。设备库和设备 API 的问题在于,有各种各样的编程 no-no 是从文字设备(或设备产品线)功能中衍生出来的:
- 硬编码设置
- 扩展
- 宏
- 设备功能的特定捆绑包或子集
- 利用宏和助手 类 构建结构(结构构建结构)
- 没有简化假设:cross-platforming 和设备测试
的大量错误处理包袱
- 等等
代码结束了——无论开发者多么努力,我知道不可能有更好的结果——非常冗长和复杂。换句话说,它在功能上很简单,但很难理解。
通常,我可能会形成 structs
来打包并隐藏 hard-coded 内容,但现在我使用 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
的构图可能吗?如果是这样,是否可以在上面概述的模板语法中完成?如果不是,是否有一些“更好”或“预期”的方式来代替?
您可以使用 requires
子句来约束 foobar
,或者命名您想要的概念的连词。
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);
};
您可以使用 &&
、||
和 !
及其通常的布尔值组合概念。
这个标题似乎受到了很多批评。但是,我发现这个概念很难搜索。它在 C++ 领域也相对较新,学校仍在教授 C++11
。
避免XY-Problem
的动机和背景现在,作为逆向工程(和学习)过程的一部分,我正在使用 concepts
检测一个嵌入式设备项目。设备库和设备 API 的问题在于,有各种各样的编程 no-no 是从文字设备(或设备产品线)功能中衍生出来的:
- 硬编码设置
- 扩展
- 宏
- 设备功能的特定捆绑包或子集
- 利用宏和助手 类 构建结构(结构构建结构)
- 没有简化假设:cross-platforming 和设备测试 的大量错误处理包袱
- 等等
代码结束了——无论开发者多么努力,我知道不可能有更好的结果——非常冗长和复杂。换句话说,它在功能上很简单,但很难理解。
通常,我可能会形成 structs
来打包并隐藏 hard-coded 内容,但现在我使用 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
的构图可能吗?如果是这样,是否可以在上面概述的模板语法中完成?如果不是,是否有一些“更好”或“预期”的方式来代替?
您可以使用 requires
子句来约束 foobar
,或者命名您想要的概念的连词。
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);
};
您可以使用 &&
、||
和 !
及其通常的布尔值组合概念。