Semantics of template specialization or separate functions - c++

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?

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.

Related

void*, extension and template. pros and kontras

Sometimes I have a problem and see 3 ways of implementing the solution. I want to know when to use which of these 3 different implementations. Below there are some exsamples, to see what I mean. I also wrote some pros/kontras which I think is correct. If something seems to be wrong, then please tell me and I'll change that.
void* example:
void method(void* value)
{
//save value as member
}
pro void*:
void* can save every type and you don't have to use templates (in headers).
kontra void*:
-when you have a list of void* you can store in index[1] another type than in index[2] which is critical, because you don't know which type it is. But with dynamic_cast you can check if you can cast it to the type or not.
-when you have a void* list with entities of the same class which have 2 variables, you can not sort by variable1 / variable2 without casting it back to the original class.
Extension exsample:
Creating a new class and extent it on another class:
class CTestClass
{
void Method1();
};
class CTest2 : CTestClass
{
//use somehow the method
};
std::vector<CTestClass> list;
pro Extension:
this way of implementing a class can be usefull, if you need a method which is in every object you need. For example you want to sort by a variable. In such a method you can make the compare.
kontra Extension:
much effort
exsample template:
template <class T>
class CTest
{
//do some stuff
};
pro template:
in a template list, you can not add different types at the same time.
kontra template:
when you have a template list of type T and T has for exsample 2 variables. You can not say: sort by variable1 or variable2 because you can not get into the class T.
As far as I know: you have to implement the template into the header file, which is ugly to see.
I hope everyone understands what I mean.
Is void* a good way to program?
Can I write templates also in .cpp files?
What do you think when to use which of this techniques? Is there some kind of rule?
The statement below is incorrect
pro void*:
void* can save every type and you don't have to use templates (in
headers).
Templates haver their closest equivalent in cross macros and not in void pointers, but exist for a different set of purposes than the mere polymorphism afforded by void pointers. Using void pointers in no way substitutes templates.
While modern programmers might not recommend about using void pointers, complaining about the (true!) potential dangers afforded, old school C-style code certainly has a use for them and this is the reason they exist. Pairing the benefits gained from void pointers with the tradeoff in performance by the C++ dynamic cast, would simply spoil the choice.
Void pointers just exist to offer limitless flexibility at managing memory when you know what you are doing and should be used only in that case. There is no comparison between them and templates.
A method that takes a void * argument should only exist when:
Case 1: The size of the passed data is known and the argument is considered as raw data. It makes no difference what that data is.
Case 2: The size of the passed data is known and you plan to convert it to a pointer of the appropriate type later (for example by some parsing, enumeration policy, known type, etc) but in order to go through some general purpose functions, libraries, APIs, you must convert it to known-length void* inbetween.

C++ make member object unnamed

I want to write convinient Color management class, that would allow me to use different orders of components and basically different setups. I want it to be distinguishable at compile-time.
Lets say I have this code:
template <typename _valueType>
struct RGBAColorData {
using ValueType = _valueType;
union {
struct { ValueType r, g, b, a; };
ValueType components[4];
};
};
This (even if anonymous structs are non-standard) works fine, when I want to use it like this:
RGBAColorData color;
color.r = whatever;
However, this is not the final form of my code. I want it to have "owning" class template, that would in compile-time select between XYZColorData. Lets say it looks like this:
template <typename _valueType, template <typename> _dataScheme>
struct Color
{
using ValueType = _valueType;
using DataScheme = _dataScheme<ValueType>;
// what now?
// DataScheme data; // ???
};
This makes a problem, because I want my code to be used like this:
using RGBAColorF = Color<float, RGBAColorData>;
RGBAColorF brushColor;
brushColor.r = whatever;
This would make a really convinient way to use colors, however I can't think of any solution to this problem.
Finally, maybe I have wrong approach to this and maybe this can be done with less effort, however I can't think about any other method that wouldn't involve massive amount of template class specializations.
Don't do it !
Tricking around for obtaining some nice syntactic effects is full of danger and might obliterate future evolution.
First of all, in C++ only one union member can be active at any moment. so switching the use of the array and of the struct is not guaranteed to work, even if on many compilers this may lead to the expected results.
Then, there is no guarantee for structure members to be contiguous, so that if mixing use of array and struct would work, it might still not lead to a correct result, even if on many compilers this will work as expected.
Or do it with a safer approach...
If you still like to mix the use of specific color components r, g, b and of the array, you should consider a safer approach:
template <typename _valueType>
struct RGBAColorData {
using ValueType = _valueType;
ValueType components[4];
ValueType &r=components[0], &g=components[1],
&b=components[2], &a=components[3]; // ATTENTION (see explanations)
};
ATTENTION: I made it quick and dirty. You should better implement the rule of three, with a proper constructor, a copy constructor and an assignment operator, to make sure that the references are not messed up.
I do not like this solution so much, but it works safely (online demo): the trick is to make r, g, b, a references to specific array items. You are then sure that you can mix the access way, and you are absolutely sure that the mapping between the two is correct.
But prefer clean encapsulation
The problem with your initial approach and my workaround is that they oth break the encapsulation: you have to know the inner structure of your color in order to use it.
With this approach, you'll never able to evolve. For example switching to a CMYK color scheme, or adopting a bit fields encoding would be compromised.
The proper way would be to have a set of getters and setters to completely hide the inner structure to the outside world. Of course, syntactically it does not look so nice, but then you'd really be able to write truly generic color code, where the encoding scheme could be a compile-time strategy.
Finally, I decided to use inheritance (as Ben Voigt said).
I fixed the other problem, with unions that made code unsafe, using the brilliant method proposed by this answer:
https://stackoverflow.com/a/494760/4386320

Enforce type safety in C++ without using extra classes

I am somewhat familiar with type safety, and have used it successfully before in methods which receive several parameters of the same type (bool) to avoid confusion. For example:
// Old version of the method
void sendPackage(bool sendImmediately, bool dividePacket);
// Type safe version
enum SendImmediatelyPreference
{
SEND_IMMEDIATELY,
DO_NOT_SEND_IMMEDIATELY
};
enum PacketDivisionPreference
{
DIVIDE_PACKET,
DO_NOT_DIVIDE_PACKET
};
void sendPackage(
SendImmediateltPreference immediatePref,
PacketDivisionPreference divisionPref);
So the cryptic sendPackage(true, false) becomes sendPackage(SEND_IMMEDIATELY, DO_NOT_DIVIDE_PACKET).
The problem is that this is only an option for bool. I have a method that accepts several std::vector<std::string> and I'd like to minimise the posibility of the user inputting the arguments in the wrong order.
I can think of creating different classes which contains an std::vector<std::string> and either override tons of the std::vector methods or expose the internal vector.
Is there an easier way, some sort of typedef which enforces type safety? Using boost would be okay.
How about an alternative approach using named parameters? There are several ways of going about this in C++ described here. The tag approach using a tuple looks reasonable. There is also boost parameter.
This doesn't offer strong type safety, but you could argue that the user is just as likely to call the wrong constructor to make their type safe object as they are to use the wrong tag when calling your function. This situation is less likely to occur if the types are used throughout your application vs defined only for one particular function.
See also the discussion of boost strong typedef vs parameter for a similar purpose here.
Not sure I understood you correctly, but maybe this can help:
enum SendImmediatelyPreference : bool // allows only 2 options:
{
DO_NOT_SEND_IMMEDIATELY, // false
SEND_IMMEDIATELY // true
}
What about creating a class that inherits (public) from std::vector to have a strong typecheck. The advantage is that you only need to rewrite constructors..
You can also regroup your parameters in a std::unordered_map>, to implement argument as a dict (like in python, or javascript)
BOOST_STRONG_TYPEDEF is precisely a typedef which enforces type safety.
However, this answer provides some caveats related to using this strong typedef for just a function, and argues that the types should be used all over the code to prevent unnecessary castings.
I like to bundle the parameters in a config class or struct. For example:
struct SendOptions
{
bool send_immediately = false;
bool divide_packet = false;
// ...
};
void sendPackage(SendOptions options);
This has the additional advantage the extra options can be added later without needing to change the interface of sendPackage(SendOptions).
This does not increase type safety but it does help to prevent errors (especially if there are a lot of parameters), which is probably the goal you're trying to achieve.

Map with comparable key types

Lately I started working on the implementation of a graph based database system. However I ran into a little problem.
The vertices in the graph are allowed to contain properties, of any type of comparable type. I was thinking about creating a map for these, as the keys are always string based. However I don't want to be bothered at all by the actually type, the only thing I want to do is compare them and still maintain safety checks. How would I go around doing so?
As I first approach I was thinking about using boost, however it'll still give me the headache of doing some manual type checking, which I absolutely do not want to do.
In Java I would do something like this, however I'm not used with these kind of things in C++.
map<String, ? extends comparable>
The reason for this is that a property can literally be any comparable type.
Not the actual answer but a requested example:
I'm used to create templates like that:
SomeClass.h:
#guards etc
template<class T> //or whatever you need
class SomeClass {
public:
SomeClass();
T content();
private:
T m_content;
}
SomeClass.cpp:
#include "SomeClass.h"
template<class T>
SomeClass::SomeClass(){
m_content = (T) 0;
}
template<class T>
T SomeClass::content(){
return T;
}
#include "SomeClass_Specializations.h"
SomeClass_Specializations.h:
#guards etc
#include "SomeClass.h"
#include "MyMagicUint.h"
//only types that behave like unsigned int may be added!
template class SomeClass<unsigned short>;
template class SomeClass<unsigned int>;
template class SomeClass<unsigned long>;
template class SomeClass<MyMagicUint>;
If you do it like that, you can specialize a long list of some common comparable types and write a comment in which you describe what other people are allowed to add to that list (in my example, unsigned int like types for some reason).
As a result, only those which are specialized here will work (since otherwise the implementation is missing), you probably have covered most of them and in the rare cases that somebody needs another specialization, he simply adds it to the list.
In the end, doing is as strict as that might not be needed, since it won't compile anyway if some forbidden action is performed, like using the <-operator when it's not defined for that type, but if you want that strict control, you can do it like that. Of course this hasn't got the dynamic control of ? extends ..., but it has control at least. Another advantage is that you can implement the code in a CPP file as usual, instead of having to put everything in the header as required for a dynamic template, that's mostly why it is my standard.
You could of course simply write the content of the specialization file directly at the bottom of the CPP instead of including another header, but I think that the specialization header is more elegant, informing prospective users what is allowed and giving them the option to add to it without taking a look at the implementation.

A use for boost::any?

I'm not sure if this calls for boost::any. I'd rather use native templates if there's a pattern that does what I want. I have this class (which I've written here using boost::any) defined in a header:
template <typename T> class Observable;
class Report
{
typedef unordered_map<wstring, std::shared_ptr<Observable<boost::any>>> ObservationMap;
public:
void AddObservable(const wstring& name, std::shared_ptr<Observable<boost::any>> observable);
const Observable<boost::any>& GetObservable(const wstring& name) const;
protected:
ObservationMap observations;
};
and Observable is defined like this:
template <typename T>
struct Observable
{
typedef T Type;
T Quantity;
// ...
};
I would really like some way of adding Observables of any quantity type to Reports. Is there a more effective way of doing this without incurring the overhead of boost::any?
Edit: An example of code that adds observables to the report class would be something like this:
Observable<float> obs1;
obs1.Quantity = 1.1f;
Observable<int> obs2;
obs2.Quantity = 5;
Report report;
report.AddObservable("Height", obs1);
report.AddObservable("Age", obs2);
Then somewhere else I would want to read those quantities. Say I receive the report:
void DoSomethingWithReport(Report& report)
{
float height = report.GetObservable("Height").Quantity;
int age = report.GetObservable("Age").Quantity;
}
Something like that. Of course, I'd really add other methods to check if those observations are present in the report, etc. I prefer it to be generic because I don't know beforehand, at the receiving site, what it will contain, so I'd like some flexibility.
boost::any is a decently efficient way to store a value of a type you have prevented the compiler (for whatever reason or design requirement) from knowing.
If there are only a limited set of operations you want to perform on the data, you can use type erasure instead and/or a base interface class. But that requires knowing all uses for the data when you define the interface.
If you have a limited set of data types, boost::variant or the like can be more efficient than any. You can even have a variant that includes any or a type erasure object (or objects) in the set of types.
You can use reflection or similar techniques to store complex data and wrap it in any accessors (or variant) if your data is sometimes structured, which can reduce storage overhead somewhat. Basically structured data becomes a type erased type with member access by name.
Much of these techniques end up mirroring type behaviour of scripting or bytecode languages: sometimes it might be a good idea to write the part of your app that needs this amount of compile time flexibilty in a mainly runtime type checked language.
Finally you may decide you do not need all this needless runtime dynamic typing.