Suppose I have a function called loadData()
which takes a container (to be filled with data) and a CSV file. I need the following overloads:
loadData(std::vector<double>& data, const std::string& file);
loadData(QVector<double>& data, const std::string& file);
loadData(std::vector<std::complex<double>>& data, const std::string& file);
loadData(QVector<std::complex<double>>& data, const std::string& file);
loadData(std::vector<std::vector<double>>& data, const std::string& file);
loadData(QVector<QVector<double>>& data, const std::string& file);
loadData(std::vector<std::vector<std::complex<double>>>& data, const std::string& file);
loadData(QVector<QVector<std::complex<double>>>& data, const std::string& file);
QVector
is Qt's vector-like class with a similar API, but taking only one template argument T
(instead of two, like std::vector<T, A>
).
The implementation for 1-4 is almost the same (it just calls 5-8, wrapping that single vector in another vector (of the same type!).
The implementation for 5-8 is the same (it's just calling the appropriate overload of the CSV parsing function).
I may also need to add float
overloads, or QVector<std::vector<...>>
/ std::vector<QVector<...>>
overloads.
Basically, it's a huge set of overloads that I'd like to generalize.
Is it possible to combine all of them into maybe 2 function templates (one for 1D containers, another for 2D containers)?
Thanks
You can use templates and iterators based generic algorithms to reduce code duplication. For example:
Yes... require a little work but is relatively simple.
Maybe there are simpler methods but I propose the create a custom type traits that verify if a template-template is
std::vector
orQVector
Next another custom type traits to verify if a type is a floating point type of a
std::complex<T>
typeNow you can write the vector-of-vector version (that intercept also mixed
std::vector
/QVector
case) as followsand, after, the simple vector version (that wrap the first argument and call the vector-of-vector version) become
I've prepared the following full working example but (sorry) I don't have a QT platform available at the moment so I have added a fake
QVector
When writing generic code, pay particular attention to separating concerns.
There are two concerns in
loadData
:-So let's build a template for acting as the data source (which we can specialise based on the value type), and then write one overload per container type in terms of that.
First attempt: