gpt4 book ai didi

c++ - 如何优雅地编写使用模板参数隐含值的类模板?

转载 作者:搜寻专家 更新时间:2023-10-31 02:14:21 24 4
gpt4 key购买 nike

我正在编写一个源文件库,其中包含一系列以一对一关系相关的声明和宏。第一个是类别列表,作为枚举:

typedef enum {
CID_SYS, // Highest-priority devices. Reserved.
CID_CTRL, // Controlling unit, only one per segment
CID_SENSOR, // Data providers (temperature, speed, clock)
CID_BROADCAST, // Broadcast messages (system messages extension)
...
} category_id_t;

我使用此枚举来定义 16 位消息标识符,类别位作为最重要的 3 位。这些标识符在较低有效位中被分成两个可变大小的位 block 。这些 block 之一取决于上述类别。所以我还定义了一个尺寸列表作为宏,每个类别一个,如下所示:

#define SYS_MESSAGES_MAX        256
#define CTRL_MESSAGES_MAX 64
#define SENSOR_MESSAGES_MAX 8
#define BROADCAST_MESSAGES_MAX 64
...

然后很容易屏蔽类别并检索相关位,即函数 ID,它位于消息 ID 的最低有效位。以 CID_SYS 为例:

unsigned short function_id = message_id & (SYS_MESSAGES_MAX-1)

我需要一个以类别作为参数的类模板。后者隐含的类别中的消息数应该在编译时由模板类以某种方式推导出来,而无需求助于数组。类模板可能类似于以下内容:

template <category_id_t CAT>
class Manager
{
...
unsigned message_count() const { return /* a number depending on CAT */ }
};

使用 -Os 时,编译器会在编译时尽可能多地解析而不添加代码或变量。所以我想充分利用它。我目前的尝试是使用函数模板和特化:

template<category_id_t CAT>
unsigned cat_size();

template<category_id_t CAT>
class Manager
{
public:
unsigned size() const { return cat_size<CAT>(); }
};

template<> unsigned cat_size<CID_SYS>() { return SYS_MESSAGES_MAX; }
template<> unsigned cat_size<CID_CTRL>() { return CTRL_MESSAGES_MAX; }

上面的例子将是:

unsigned short function_id = message_id & (size()-1) /* This should be a constant resolved at compile-time */

通用模板函数故意没有定义,以便在我添加类别时忘记特化的情况下生成链接器错误。然而,我发现这既不优雅又令人费解。

我怎样才能让它更优雅?

我绝对不想将消息计数作为模板参数传递,因为我仍然需要 C 风格的宏:我的库应该由 C C++ 应用程序使用。 p>

最佳答案

现在我们有了 constexpr,这在没有模板的情况下实际上是可行的。 cat_size映射可以使用 constexpr 完成功能与 switch .你可以定义 *_MESSAGES_MAX作为单独的 constexpr int s 如果你不喜欢像下面这样的返回值

constexpr int cat_size(category_id_t cat) {
switch (cat) {
case CID_SYS:
return 256; // SYS_MESSAGES_MAX
case CID_CTRL:
return 64; // CTRL_MESSAGES_MAX
case CID_SENSOR:
return 8; // SENSOR_MESSAGES_MAX
case CID_BROADCAST:
return 64; // BROADCAST_MESSAGES_MAX
}
}

计算函数id只是另一个constexpr调用交换机。我已经替换了 unsigned shortstd::uint16_t为了确保你得到你想要的,请注意这需要你 #include <cstdint>

constexpr std::uint16_t function_id(category_id_t cat, std::uint16_t msg) {
return msg & (cat_size(cat)-1);
}

查看下面生成的程序集,我们可以看到它实际上是在编译时计算的

int main() {
constexpr std::uint16_t msg{0xCDEF};
constexpr auto fid = function_id(CID_SYS, msg);
std::cout << fid << '\n';
}

关于c++ - 如何优雅地编写使用模板参数隐含值的类模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40027750/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com