模板特化或单独函数的语义

时间:2013-11-21 08:43:18

标签: c++ templates enums semantics

我正在围绕C库libnetfilter_conntrack创建一个C ++包装器,它使用函数nfct_set_attr(...)。它需要enum来定义要设置的属性的类型,以及传递数据的void*(根据属性而不同)。由于这是C ++,我想使它类型安全,所以我需要为每个属性类型单独的函数。但是为了提高兼容性,我创建了一个enum class,用于定义libnetfilter_conntrack中可用的所有属性类型。

我最初的想法是创建模板set_attr(...)函数,这些函数根据需要设置的属性获取模板。例如:

template<attr_type, typename T> void set_attr(T); // designed to fail
template<> void set_attr<orig_ipv4_src, unsigned long>(unsigned long ip) {};

这种方法的优点是可以直接将enum class定义链接到函数,这可能会使逻辑更加清晰。但我想到了另一种可能的选择,为每个属性使用单独的函数:

void set_orig_ipv4_src(unsigned long ip) {};

在函数内部,无论如何都将使用enum class(以调用底层的C例程),因此这些定义仍然存在。

上述两种方法中的哪一种更有意义?使用模板版本是否存在任何固有问题?性能问题?

1 个答案:

答案 0 :(得分:1)

编写的模板方法确实存在问题。考虑:

long ip = get_ip();
set_attr<orig_ipv4_src>(ip);

此代码无法编译。即使long可以转换为unsigned longs,我们最终会回到通用模板中,该模板可能包含static_assert(false)。

有一种方法可以解决这个问题:

template<attrt ATTR>
struct attr_info {
  typedef void argtype;
};
template<>
struct attr_info<orig_ipv4_src> {
  typedef unsigned long argtype;
};
// etc.
template<attrt ATTR>
void set_attr(attr_info<ATTR>::argtype arg) {
  // set the attr
}

这将很好地进行类型推广。如果您愿意,它还可以让您以其他方式获取此信息。

尽管如此,我还不确定这种方法与单独的功能相比有什么实际优势。也就是说,我不确定这能实现的是任何人都想做的事情。对项目新手来说,需要做更多的工作才能理解。

我建议查看旧的c代码并查看是否有人使用非文字的第一个参数调用此函数。如果是这样,请确保他们在新系统中可以执行的操作。如果没有,可能会使用单独的功能。