Frage

I am creating a C++ wrapper around the C library libnetfilter_conntrack, which uses the function nfct_set_attr(...). It takes an enum that defines the type of the attribute to set, along with a void* to pass in the data (which is different depending on the attribute). Since this is C++ I want to make it type-safe, so I need separate functions for each attribute type. To aid compatibility however, I created an enum class that defines all the attribute types available from libnetfilter_conntrack.

My original idea was to create templated set_attr(...) functions that take a template depending on the attribute that needs setting. For example:

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

This approach has the advantage of directly linking the enum class definitions to the functions, which might make the logic slightly clearer. But I thought of another potential option, to use separate functions for each attribute:

void set_orig_ipv4_src(unsigned long ip) {};

Inside the function the enum class will be used anyway (to invoke the underlying C routine), so those definitions will still exist.

Which of the two methods above makes more sense? Are there any inherent problems using the template version? Performance issues?

War es hilfreich?

Lösung

The template approach as written does have a problem. Consider:

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

This code does not compile. Even though longs can be converted into unsigned longs, we wind up back in the generic template which presumably contains static_assert(false).

There is a way to fix this:

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
}

This will do type promotion nicely. It will also let you get at this information in other ways if you want.

Still, for all its prettiness, I'm not sure this approach has any practical advantages over separate functions. That is, I'm not sure the things this enables are things anyone will ever want to do. And it will take more work for someone new to the project to understand.

I would propose looking through the old c code and seeing if anyone ever invokes this function with a non-literal first parameter. If so, make sure what they're doing is possible in the new system. If not, probably go with separate functions.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top