1

I would like to design a wrapper in C++ with a simple syntax:

Vector<double,stl> v; // aka std::vector<double>
Vector<double, eigen> w; // aka Eigen::VectorXd from Eigen library
Matrix<double, eigen> m; // aka Eigen::MatrixXd from Eigen library

However, I do not manage to get this syntax, especially for the two last examples. Here is my code for the case of wrapping of STL vectors:

#ifndef WRAPPER_HPP
#define WRAPPER_HPP

#include <cstdlib>
#include <vector>

//=============
// BASE WRAPPER
//=============

template<class ScalarType, template<class,class...> class WrappedType>
class Wrapper
{
protected:
  WrappedType<ScalarType> wrapped_;
};

//==============
// STL WRAPPER
//==============

template<class ScalarType, template<class,class...> class WrappedType>
struct stl;

template<class ScalarType>
struct stl<ScalarType,std::vector> : public Wrapper<ScalarType,std::vector>
{
public:
  size_t size()
  { return this->wrapped_.size(); }
};

//=======
// VECTOR
//=======
template<class ScalarType, template<class, template<class,class...> class> class Wrapper>
using Vector = Wrapper<ScalarType,std::vector>;
// **** Problem : I should not provide "std::vector" above ****

#endif

STL wrapper is a structure called stl. This structure is actually a subclass of Wrapper class. I have specialized stl structure for STL's vectors. I may do some other specalizations for some containers (lists, maps, ...). Thus, when declaring

Vector<double,stl> vec

I would like to be able to deduce from the pair (Vector, stl) that it corresponds to the specialization of stl for std::vector. However, I do not manage to do it. Each time I try something, I get an infinite recursion over template parameters.

There may be a good way to do this with some typedef or template alias but I cannot find it. It may be something like that:

template<class ScalarType, template<class, template<class,class...> class> class Wrapper>
using Vector = Wrapper<ScalarType,????>;

where ???? would be something equivalent to std::vector, but deduced from Wrapper. But I do not know if it is possible.

My design may also be naive. I would really appreciate any suggestion to improve it. I am only interested in the syntax of the code.

Thanks!

Aleph
  • 1,343
  • 1
  • 12
  • 27
  • Why would you want something like that? The classes seem pretty unrelated and just happen to share similar *names*. – Christian Hackl Mar 08 '15 at 17:39
  • Could you explain further what you mean? I would like to wrap external libraries, but whithout virtual functions (to maintain performances of wrapped libraries). – Aleph Mar 08 '15 at 17:48
  • I don't see what `std::vector` and `Eigen::VectorXd` have in common other than the similar name and the very broad generalisation of "contains elements". – Christian Hackl Mar 08 '15 at 17:49
  • Just consider any other library you have in mind (blas, eigen, armadillo, ...). I only take the example of std::vector because linear algebra may not be well known by people who may be able to help me. – Aleph Mar 08 '15 at 17:56
  • 1
    I think I've not made my point clear enough. You have completely unrelated things A and B. Now you want to "wrap" them as an abstract "C". But such an abstraction is pretty useless. Whenever you use a C for anything, you will treat it specifically as A or as B. Can you provide a piece of code in which it does *not matter* if I am really dealing with a `std::vector` or an `Eigen::Vector2d`? – Christian Hackl Mar 08 '15 at 18:00
  • Yes, they're unrelated. But what's being asked is to how to implement a simple template-based type aliasing, for declaration purposes only. Where things went astray here, is trying to do this via subclassing, when the right approach is to combine specialization, with "template ... using". – Sam Varshavchik Mar 08 '15 at 18:10
  • Christian, you're clear and you're right. But as Sam points out, my question does not really concern STL vectors. This is just a toy example. As you guessed, my real goal is to wrap similar objects from several libraries, such as vectors and matrices sharing identical functionalities (see blas, lapack, eigen, armadillo, ...). – Aleph Mar 08 '15 at 19:09

1 Answers1

2

This is fairly easy to do using C++11 syntax, or higher.

Here's an example of implementing a Vector wrapper, that will result in the syntax that you're looking for. Use a similar approach to implement Matrix, etc.

The approach combines template specialization, with template using, selecting the correct specialization that declares a member type that's the actual type being declared:

#include <vector>

class stl; // dummy class
class eigen; // dummy class

template<typename ...Args> class vector_impl;

template<>
class vector_impl<double, stl> {

public:
    typedef std::vector<double> impl_type;
};

template<>
class vector_impl<double, eigen> {

public:
    typedef Eigen::VectorXd impl_type;   // I presume...
};

// And the magical alias:

template<typename ...Args>
using Vector=typename vector_impl<Args...>::impl_type;

With the above being defined:

Vector<double, stl> a;    // This declares a std::vector<double>
Vector<double, eigen> b;  // This declares an `Eigen::VectorXd`

Using variadic templates allows for some further work, namely a few additional tweaks can also result in some extras, like forwarding custom allocator types to std::vector, etc...

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • Thank you very much for your help. Not only your solution fits exactly my syntaxic needs but it also leads to a very simple and clear code. – Aleph Mar 08 '15 at 18:51