这个头文件是 C 中 `_Generic` 的一个很好的用例吗?

问题描述 投票:0回答:1

我正在用 C 语言编写一个侵入式数据结构库。其中许多容器将共享功能。例如,将会有许多容器提供正向和反向迭代。因此,我创建了一个标头,将这些通用操作作为跨所有容器的宏提供。这只是前向迭代器。

#include "double_ended_priority_queue.h"
#include "ordered_map.h"
#include "realtime_ordered_map.h"

#define BEGIN(container_ptr)                                          \
    _Generic((container_ptr),                                         \
        double_ended_priority_queue *: depq_begin,                    \
        ordered_map *: om_begin,                                      \
        realtime_ordered_map *: rom_begin)(container_ptr)

#define NEXT(container_ptr, iter_elem_ptr)                            \
    _Generic((container_ptr),                                         \
        double_ended_priority_queue *: depq_next,                     \
        ordered_map *: om_next,                                       \
        realtime_ordered_map *: rom_next)((container_ptr),            \
                                          (iter_elem_ptr))

用法如下所示。

struct val
{
    int id;
    int val;
    ccc_depq_elem elem;
};

void
inorder_fill(int vals[], size_t size, double_ended_priority_queue *pq)
{
    if (depq_size(pq) != size)
    {
        return;
    }
    size_t i = 0;
    for (struct val *e = BEGIN(pq); e && i < size; e = NEXT(pq, &e->elem))
    {
        vals[i++] = e->val;
    }
}

这看起来不错,并且这样的功能可以扩展到许多其他操作(emplace、Rust 的 Entry API、范围等)。但是,我必须将所有容器的标头包含在文件顶部的

_Generic
列表中。否则,当用户包含
generics.h
文件时,他们将收到编译错误,其中未包含的
_Generic
中的所有类型情况均包含未知类型。

随着更多共享这些功能的容器的实现,

generics.h
文件中包含的数量将大大增加。虽然
_Generic
的使用没有运行时开销,但我似乎用这种方法造成了巨大的编译时间膨胀。

  • 我是否误解了
    _Generic
    的良好用例?
  • C 中还有另一种泛型方法吗?或者我是否正在尝试解决不存在的问题,并且每个容器单独提供此功能都可以?
c api generics compilation intrusive-containers
1个回答
0
投票

我想说代码非常好。

也许可以考虑将整个循环放在函数中以使代码更具可读性,而不是使用一些神秘的

BEGIN
/
NEXT
宏。

如果函数已经就位且无法修改,则考虑包装函数(它将被内联/优化)。

也就是说,创建一个像

container_iterate()
这样的宏,并且该宏使用
_Generic
检查容器的类型,然后调用例如
depq_iterate
,它是一个包含 for 循环和对
depq_begin
/
depq_next 的调用的包装函数
.

至于在添加更多类型时维护大量宏 - 总有 X 个宏,其中除其他外可用于生成

_Generic
关联列表,甚至是函数模板。它们以牺牲可读性为代价来提高可维护性。但这也许是一个单独问题的材料。

© www.soinside.com 2019 - 2024. All rights reserved.