suppose I have an object like this:
class Spline {
public:
Spline(std::size_t const dim);
// Quite a few functions here. One of those:
vec operator()(double const t) const; // Returns vector of dimension d
}
Now, at most uses of this class, the dimension will already be determined at compile time, thus it would be a good idea (for performance reasons) to change the class like this:
template <std::size_t dim>
class Spline {
public:
Spline();
// Quite a few functions here. One of those:
vec::fixed<dim> operator()(double const t) const; // Returns vector of dimension d
}
(For those who wonder, vec and vec::fixed are objects defined by the armadillo linear algebra library). Now I would like to have both versions living in parallel, thus being able to choose the dimension at compile time as well as during runtime. In short, I would like to create the equivalent of vec::fixed<dim> as Spline::fixed<dim>, but without implementing all functions twice. Especially, I would have to choose the return type of all those functions depending on whether there is a template argument present or not.
Do you have any idea how I might accomplish this, especially thinking in terms of a clear and maintainable design? (In the hope that I made myself clear, which I am not totally sure about.)
Use a simple traits metastruct and specialize that.
template<std::size_t dim>
struct spline_return_traits{
typedef vec::fixed<dim> type;
};
template<>
struct spline_return_traits<0>{ // 0 is a special marker for runtime dimensions
typedef vec type;
};
template<std::size_t dim>
class Spline_impl{
typedef typename spline_return_traits<dim>::type spline_return;
public:
spline_return operator()(double const t) const;
// if <dim> is 0, then the dynamic vec will be chosen as the return type
// all your functions
};
class Spline : public Spline_impl<0>{ // default is dynamic
public:
template<int dim>
struct fixed : public Spline_impl<dim>{
};
};
Now you simple use that. :) Every operator, constructor and function of Spline_impl should be available in the subclasses. For the implementation of each function, you need to do some branching where it's a must to decide between runtime or fixed vec:
if(dim == 0){
// runtime specific stuff
}else{
// compile-time specific stuff
}
Use as:
Spline dynamic_spline;
Spline::fixed<10> fixed_10_spline;
Only problem being that the Spline class will be double the size of Spline_impl... :/ Lemme think if I can find a solution to that too.
Edit: If you don't want Spline to be double the size of Spline_impl, one possibility is to add a little verbosity and a typedef:
class Spline : public Spline_impl<0>{ // default is dynamic size
public:
template<std::size_t dim>
struct fixed{
typedef Spline_impl<dim> type;
};
};
And use as
Spline dynamic_spline;
typename Spline::fixed<10>::type fixed_10_spline;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With