Declare member function only for specific template instantiation of class - c++

Is it possible to declare a member function only for specific template instantiations of a class? This is why I want to do it:
// Polynomial<N> is a polynomial of degree N
template<int N>
class Polynomial {
public:
//... various shared methods e.g...
double eval(double x) const;
Polynomial<N-1> derivative() const;
Polynomial<N+1> integralFrom(double x0) const;
// ... various shared operators etc.
double zero() const; // only want Polynomial<1> to support this
// only want Polynomial<2> and Polynomial<1> to support the following
// because the solutions rapidly become too difficult to implement
std::vector<double> zeros() const;
std::vector<double> stationaryPoints() const { return derivative().zeros();}
private:
std::array<double,2> coeffs;
}
My current workaround is to just throw an exception from Polynomial<N>::zeros() for N>2 but it would have been nice to detect the problem at compile-time.

You can also use std::enable_if to SFINAE away the zero function.
template< int I >
class Poly {
public:
template<int Ib = I, typename = std::enable_if_t<Ib == 1> >
double zero()
{
return 42;
}
};
int main()
{
Poly< 10 > does_not_compile;
does_not_compile.zero();
//Poly< 1 > compile;
//compile.zero();
}

You can use CRTP to implement zeros and zero in a base class that knows about the derived one.
Then conditionally derive from one that has zeros and/or zero, or not.
template<class P>
struct zeros { /* todo */ };
template<class P>
struct zero:zeros<P> { /* todo */ };
struct nozero {};
template<int N>
struxt Polynomial:
std::conditional_t<
(N==1),
zero<Polynomial<N>>,
std::conditional_t<
(N==2),
zeros<Polynomial<N>>,
nozero
>
>
{
// body
};

Your solution is template specialization, in this case, full specialization.
However, I think you would need to think about your design. Generally, it is not a good idea to define different interfaces for different cases because you are not taking advantage of the abstraction.
For example, think about your stationaPoints() function. This functions should not be available for Polynomial<2> because the derivative is a Polynomial<1> which does not have the zeros() function. Your solution is to add the zeros function to the Polynomial<1> in order to homogenize the interface.
For your case, I guess you would like a solution which includes a N-1 c-vector inside the polynomial type with the zeros and a zero(i) function to get them. Something like this:
template <int N>
class Polynomial {
double _coefs[N+1];
double _zeros[N];
public:
double zero(size_t i) const { assert(i<N); return _zeros[i]; }
// ...
};
In this case, you could decide the strategy to calculate de zeros, depending on your application: constructor?, adding a boolean to know if it has been calculated then it is calculated in the first call to zero, etc...
I guess this solution could be more interesting for you because if you prefer a c-vector to store the coeficients, you wouldn't like the vector based interface of your zeros() function, would you?

Related

partial specialization with inheritance. Can I avoid inheritance?

I am writing a vector class and I would like it to have the following characteristics:
Use static allocation on the stack whenever possible (to avoid calling new for efficiency).
Be able to be instantiated from a pointer if the user prefers to provide a previously allocated array.
The class needs to be easily converted to a simple pointer. This allows to use previously written routines in C.
Find below this simple test problem with the solution I came up with. I use inheritance so Vector inherits from Vector_base which provides a common interface (pure virtual) for all vectors.
Then I define an empty class Vector that allows me then using partial specialization to have different storage schemes; static or dynamic.
The idea behind this is that I just want vector to be a C++ wrapper to the old-fashioned static array.
I like the implementation below. I'd like to keep the interface I came up with in main.
What I don't like is that sizeof(Vector3) = 32 when in C a vector of three doubles is 24 bytes. The reason for this is the extra 8 bytes of the virtual table.
My question: can I somehow come up with another design that would provide me with the same interface but the vector only has 24 bytes?
Summarizing:
I'd like have a Vector3 of 24 bytes, as in C.
I still want to have arbitrarily large vectors though (with <double,n>)
I'd like to keep the interface used in main().
Could I use a programming idiom like traits or polices for this? I am very new to those and I don't know if they could provide a solution.
Find my little test code below:
#include <iostream>
using namespace std;
#define TRACE0(a) cout << #a << endl; a;
#define TRACE1(a) cout << #a "=[" << a << "]" << endl;
enum alloc_type {Static,Dynamic};
template <class T>
class Vector_base{
public:
Vector_base(){}
virtual operator T*() = 0;
virtual T operator[](int i)const = 0;
virtual T& operator[](int i) = 0;
virtual int size() const = 0;
friend ostream& operator<<(ostream &os,const Vector_base& v){
for (int i=0; i<v.size(); i++)
cout << v[i] << endl;
return os;
}
};
// base template must be defined first
template <class T, int n,alloc_type flg=Static>
class Vector{};
//Specialization for static memory allocation.
template <class T, int n>
class Vector<T,n,Static>: public Vector_base<T>{
public:
T a[n];
public:
Vector() {
for (int i=0; i<n; i++) a[i] = 0;
}
int size()const{return n;}
operator T*(){return a;}
T operator[](int i)const {return a[i];}
T& operator[](int i){return a[i];}
};
//Specialization for dynamic memory allocation
template <class T,int n>
class Vector<T,n,Dynamic>: public Vector_base<T>{ //change for enum. flg=0 for static. flg=1 for dynamic. Static by default
public:
T* a;
public:
Vector():a(NULL){
}
Vector(T* data){ //uses data as its storage
a = data;
}
int size()const{return n;}
operator T*(){return a;}
T operator[](int i)const {return a[i];}
T& operator[](int i){return a[i];}
};
//C++11 typedefs to create more specialized three-dimensional vectors.
#if (__cplusplus>=201103L)
template <typename Scalar,alloc_type flg=Static>
using Vector3 = Vector<Scalar,3,flg>;
#else
#error A compiler with the C++2011 standard is required!
#endif
int main(){
cout << "Testing Vector3: " << endl;
//Vector<double,3> v3;
Vector3<double> v3;
TRACE0(cout << v3 << endl;);
TRACE1(sizeof(v3));
//Vector<double,3,Dynamic> v0(v3);
Vector3<double,Dynamic> v0(v3); //calls Vector<double,3,Dynamic>::Vector(double*) and uses the conversion operator on v3.
TRACE1(sizeof(v0));
TRACE1(sizeof(double*));
TRACE0(v3[1] = 2.1;);
TRACE0(cout << v0 << endl;);
return 0;
}
All the features you want are offered as Standard or can be plugged in to existing Standard extension points.
Use static allocation on the stack whenever possible (to avoid calling new for efficiency).
Meet std::array<T, N>. It's a C++ wrapper on a C array and presents all the same characteristics.
Be able to be instantiated from a pointer if the user prefers to provide a previously allocated array.
Meet Allocators. You can code an allocator that meets the requirement that gives back already allocated memory, then simply use std::vector. Such an allocator is under consideration for future Standards along with other allocator enhancements like polymorphic allocators.
The class needs to be easily converted to a simple pointer. This allows to use previously written routines in C.
Both std::vector and std::array offer this as a triviality.
If you want to offer this choice at runtime, consider boost::variant. Rolling your own discriminated union- not advised.
If I understand you correctly, something like LLVM's SmallVector seems to fit the bill. It has a template parameter declaring the maximum size you want allocated on the stack, and switches to heap memory only when it grows outside that range.
If it doesn't fit your interface directly, I'm sure looking at the implementation will be very useful towards writing something similar yourself.
You are talking about two policies for locating the data: either inline as a small-array optimization, or via indirection with a pointer to a dynamically allocated buffer.
There are two ways to make that policy choice: With static type information, or dynamically. The dynamic choice requires storage to indicate whether any particular vector uses the static or dynamic policy.
For a vector of doubles, you can perhaps use an illegal value in the first element (a NaN encoding) to indicate that the dynamic policy is in effect (the pointer needs to be stored overlapping the remaining elements, use a union for this).
But in other data types, all possible bit patterns are valid. For those you will require additional storage to select the policy. You might know for a particular problem that a particular bit isn't needed for the range of values, and can be used as a flag. But there's no general solution applicable to all data types.
You probably want to look at implementations of the "small string optimization". They are making the same tradeoff for improved locality of reference when the data is small enough to store directly inside the object, and also generally trying to avoid using mode space than necessary.
One thing is for sure. In order to avoid significantly increase in space requirements, you're going to need close coupling. No specialization, no inheritance, just one monolithic class that implements both policies.
Ok guys. It took me all day but this is the solution I came up with and it does exactly what I want. Please share your comments and suggestions to this solution.
Of course I didn't implement all methods I want. I only implemented two fake dot products to show how specific C implementations are chosen at compile time by use of templates.
The scheme is quite more complex than what I thought it would be. The basic concepts I'm using to accomplish my design requirements are:
the curiously recurring template pattern.
Partial specialization
Traits
Compile-time selection with templates (see how I decide what dot product implementation to use).
Again, thanks and please comment!! See code below
#include <iostream>
using namespace std;
#include <type_traits>
//C++11 typedefs to create more specialized three-dimensional vectors.
#if (__cplusplus<201103L)
#error A compiler with the C++2011 standard is required!
#endif
template<class T>
struct traits{};
#define TRACE0(a) cout << #a << endl; a;
#define TRACE1(a) cout << #a "=[" << a << "]" << endl;
enum {Dynamic = -1};
template<typename T,int n>
struct mem_model{
typedef T array_model[n];
};
//Specialization to Dynamic
template<typename T>
struct mem_model<T,Dynamic>{
typedef T* array_model;
};
template<class derived_vector>
struct Vector_base: public traits<derived_vector>{ //With traits<derived_vector> you can derive the compile time specifications for 'derived_vector'
typedef traits<derived_vector> derived;
typedef typename traits<derived_vector>::Scalar Scalar;
public:
inline int size()const{ //Calling derived class size in case a resize is done over a dynamic vector
return static_cast<const derived_vector*>(this)->size(); //derived_vector MUST have a member method size().
}
inline operator Scalar*(){return a;} //All vectors reduce to a Scalar*
inline bool IsStatic()const{return (n==Dynamic)? false: true;}
inline int SizeAtCompileTime()const{return n;} //-1 for dynamic vectors
protected:
using derived::n; //compile time size. n = Dynamic if vector is requested to be so by the user.
typename mem_model<Scalar,n>::array_model a; //All vectors have a Scalar* a. Either static or dynamic.
};
//Default static
template<typename Scalar,int n>
class Vector:public Vector_base<Vector<Scalar,n> >{ //Vector inherits main interface from Vector_base
public:
//Constructors
Vector(){
//do nothing for fast instantiation
}
Vector(const Scalar& x,const Scalar& y,const Scalar& z){
a[0] = x; a[1] = y; a[2] = z;
}
//
inline int size()const{return n;}
private:
using Vector_base<Vector<Scalar,n> >::a;
};
//Traits specialization for Vector. Put in an inner_implementation namespace
template<typename _Scalar,int _n>
struct traits<Vector<_Scalar,_n> >{
typedef _Scalar Scalar;
enum{
n = _n
};
};
double clib_dot_product_d(const int n,double* a,double* b){
double dot = 0.0;
for(int i=0;i<n;i++)
dot += a[i]*b[i];
return dot;
}
float clib_dot_product_f(const int n,float* a,float* b){
cout << "clib_dot_product_f" << endl;
return 1.0;
}
template<typename Scalar>
struct dot_product_selector{};
template<>
struct dot_product_selector<double>{
template<class derived1,class derived2>
static double dot_product(Vector_base<derived1> &a,Vector_base<derived2> &b){
return clib_dot_product_d(a.size(),a,b);
}
};
template<>
struct dot_product_selector<float>{
template<class derived1,class derived2>
static float dot_product(Vector_base<derived1> &a,Vector_base<derived2> &b){
return clib_dot_product_f(a.size(),a,b);
}
};
template<class derived1,class derived2>
typename Vector_base<derived1>::Scalar dot_product(Vector_base<derived1> &a,Vector_base<derived2> &b){
//run time assert checking the two sizes are the same!!
//Compile time (templates) check for the same Scalar type
static_assert( std::is_same<typename Vector_base<derived1>::Scalar,typename Vector_base<derived2>::Scalar>::value,"dot product requires both vectors to have the same Scalar type");
return dot_product_selector<typename Vector_base<derived1>::Scalar>::dot_product(a,b);
}
#if 0
template <typename Scalar,alloc_type flg=Static>
using Vector3 = Vector<Scalar,3,flg>;
#endif
int main(){
cout << "Testing Vector3: " << endl;
Vector<double,3> as;
Vector<double,Dynamic> ad;
TRACE1(sizeof(as));
TRACE1(sizeof(ad));
TRACE1(as.SizeAtCompileTime());
TRACE1(ad.SizeAtCompileTime());
Vector<double,3> u(1,2,3),v(-1,1,5);
Vector<float,3> uf,vf;
TRACE1(dot_product(u,v));
dot_product(uf,vf);
//dot_product(u,vf); //this triggers a compile time assertion using static_assert
return 0;
}
You could simplify the Vector template specialization to...
template <class T, std::size_t Size = -1>
class Vector {
// The statically allocated implementation
};
template <class T>
class Vector<T, -1> {
// The dynamically allocated implementation
};
The implementations could possibly be thin wrappers around std::vector and std::array.
EDIT: This avoid the magic constant...
template<typename T = void>
class Structure {};
template<typename T, std::size_t Size>
class Structure<T[Size]> {
T data[Size];
// The statically allocated implementation
};
template<typename T>
class Structure<T[]> {
T * pData;
public:
Structure(std::size_t size) : pData(new T[size]) {}
~Structure() { delete[] pData; }
// The dynamically allocated implementation
};
Instantiated like this...
Structure<int[]> heap(3);
Structure<int[3]> stack;
EDIT: Or use policies like so...
class AllocationPolicy {
protected:
static const std::size_t Size = 0;
};
template<std::size_t Size_>
class Static : AllocationPolicy {
protected:
static const std::size_t Size = Size_;
};
class Dynamic : AllocationPolicy {
protected:
static const std::size_t Size = 0;
};
template <typename T, typename TAllocationPolicy = Dynamic>
class Vector : TAllocationPolicy {
static_assert(!std::is_same<typename std::remove_cv<TAllocationPolicy>::type, AllocationPolicy>::value && std::is_base_of<AllocationPolicy, TAllocationPolicy>::value, "TAllocationPolicy must inherit from AllocationPolicy");
using TAllocationPolicy::Size;
public:
T data[Size];
};
template <typename T>
class Vector<T, Dynamic> : private Dynamic {
T * data;
public:
Vector(std::size_t size) : data(new T[size]) {}
~Vector() { delete [] data; }
};

template to access different members of objects passed as arguments

I have a function to compute gradient of different variable defined on set of neighbor points. The algorithm is always the same, but depending on what is computed, different member data of the neighbors are accessed, e.g. when computing gradient of velocity, use Node::velocity, when computing gradient of stress, use Node::stress. What is the best way to avoid writing the same function several times?
I had several possibilities in mind:
Pass lambda function (c++0x)
or callable object returning that particular member data in question, called like
gradVelocity=computeGradient(listOfNeighbors,[](const Node& n){ return n.velocity; });
The minus is extra function call at every read.
Template the function based on integer saying what is being computed:
enum{VAL_VELOCITY=0,VAL_STRESS,VAL_SOMETHING};
template<int what> computeGradient(const std::list<Node>& neighbors){
/*loop over neighbors*/
value=(what==VAL_VELOCITY?neighbor.velocity:((what==VAL_STRESS)?neighbor.stress:neighbor.something);
/* and so on */
}
/* called like this */
gradVelocity=computeGradient<VAL_VELOCITY>(neighbors);
It should be perhaps efficient (hoping compiler will optimize the conditional with constants away in individual instantiations), but readability and maintainability is pretty low.
Some better idea?
If all of your fields have the same types, it's easy to use pointers to members:
struct Node
{
double stress;
double velosity;
};
void foo(Node* pNode, double Node::*pValue)
{
cout << pNode->*pValue << endl;
}
int main()
{
Node n1 = { 1, 2 };
foo(&n1, &Node::stress);
foo(&n1, &Node::velosity);
}
Update: If not, it's still easy to combine pointers to members with templates:
struct Node
{
double stress;
double velosity;
int dimension;
};
template<class T>
void foo(Node* pNode, T Node::*pValue)
{
cout << pNode->*pValue << endl;
}
int main()
{
Node n1 = { 1, 2 };
foo(&n1, &Node::stress);
foo(&n1, &Node::velosity);
foo(&n1, &Node::dimension);
}
I think this is probably the most efficient possible way. It's pretty vivid too.
Pointer to member is what you need. The type is written as T S::* T is the type of the data member, S is your struct or class. Here is a small example:
#include <iostream>
struct Foo
{
int a;
double b;
Foo(int a, double b)
: a(a), b(b)
{ }
};
template<typename T, T Foo::* mem>
void print(const Foo& foo)
{
std::cout << foo.*mem << std::endl;
}
int main()
{
Foo f(5, 3.14);
print<int, &Foo::a>(f);
print<double, &Foo::b>(f);
}
I am a huge fan of Boost.Fusion, and more specifically, the Boost.Fusion.Map, which let you build a type -> value kind of map.
struct Velocity {};
struct Stress {};
typedef boost::fusion::map<
std::pair<Velocity, double>,
std::pair<Stress, int>
> Map;
Map map;
Now, you can access the map with types:
boost::fusion::at_key<Velocity>(map)
returns a reference to a variable of type boost::fusion::result_of::at_key<Velocity, Map>::type
With appropriate wrapping, you get:
extern Velocity const velocity;
extern Stress const stress;
myItem.access(stress) = 3;
And of course, since we are talking templates, no runtime penalty, at all :)
What about inheriting from Node and using virtual access? It would even be possible to use CRTP to avoid the virtual call.
You can combine velocity, stress, something in a single array and access them based on enum index.
struct Node
{
int attributes[3]; // contains 'velocity', 'stress', 'something';
enum { VAL_VELOCITY=0, VAL_STRESS, VAL_SOMETHING };
};
Usage:
Node n;
n.attributes[Node::VAL_VELOCITY] = <value>; // writing 'Node::velocity'
<otherthing> = n.attributes[Node::VAL_SOMETHING]; // reading 'Node::something'
[Note: If you want to keep attributes inside private region then provide getter and setter methods in Node for accessing them.]

advice for static template class

I have this problem (histogramming). I've a real space: [a,b] partitioned in some way ([a0=a, a1, a2, ..., b]). The partitioning may be with equal space (a1 - a0 = a2 - a1 = ...) or variables.
I need a class that handle this, with some methods to say given a value in which bin of the partition it belongs; other methods to find the center of a particular bin and more.
During the program I don't like to instantiate a class only to call these simple function like
Binner binner(binning);
binner.get_bin(1.3);
binner.get_centerbin(2);
so I tried to write a static class using template to do something like that:
Binner<binning>::get_bin(1.3);
Binner<binning>::get_centerbin(2);
is it a good idea? There are other way to do it? Now I've free functions like
double get_bin(double bin, Binning binning); // a lot of if/else inside
but I think it's too error prone.
Here my implementation:
enum Binning {CELL, LARGE, BE};
const double binning_LARGE[] = {0, 1.2, 1.425, 1.550, 1.800, 2.5};
const double binning_BE[] = {0, 1.425, 1.550, 2.5};
template<Binning binning>
class Binner
{
public:
static const double* bins;
static const int n;
static int get_bin(double value);
};
template<> const double* myclass<LARGE>::bins = binning_LARGE;
template<> const double* myclass<BE>::bins = binning_BE;
template<> const int myclass<LARGE>::n = sizeof(binning_LARGE) / sizeof(double);
template<> const int myclass<BE>::n = sizeof(binning_BE) / sizeof(double);
template<Binning binning> int myclass<binning>::get_bin(double value)
{
return find_if(bins, bins + n,
bind2nd(greater<double>(), value)) - bins - 1;
}
template<> int myclass<CELL>::get_bin(double value)
{
return static_cast<int>(value / 0.025);
}
is it a good implementation / design?
Is there a way to avoid the n field using std::vector? How?
Is there a way to parametrize the 0.025? I know that double can't be template parameter but can I write something similar to this:
Binner<0.025> binner;
other / advices?
Edit:
For the third point Why I can't do that:
template<Binning binning, int N=100>
class Binner
{
public:
static const double* bins;
static const int n;
static int bin(double value);
};
...
template<Binning binning, int N> int Binner<CELL, N>::bin(double value)
{
return static_cast<int>(value / (2.5 / N));
}
IMHO, your design is ok, if you do not want to instantiate a class. Indeed, it seems a kind of template metaprogramming to me. Whether this makes sense depends on how you are planning to reuse this template.
Using a std::vector would allow you to get rid of the variable to hold the array size, for sure. Now, if this is good for your design, I don't know... it would move some complexity out of your template definition, to the binning definition (which now you can initialize very simply)...
Finally, you can instantiate your template passing a constant to it:
template < Binning binning, unsigned long N, unsigned long M>
class ... {
<using N>
}
have you considered a traits class? Typically if you have static information that you want to separate from the behaviour in a class, you might consider creating a traits class that encapsulates that.
So I'd start with the default behaviour:
enum Binning {CELL, LARGE, BE};
template <Binning binning>
struct BinTraits
{
// default behaviour
int get_bin(double value) { return value / 0.025; }
};
Then I'd provide the specialisations:
const double binning_LARGE[] = {0, 1.2, 1.425, 1.550, 1.800, 2.5};
const double binning_BE[] = {0, 1.425, 1.550, 2.5};
template <typename RandomAccessCollectionT>
int get_bin_impl(double value, RandomAccessCollectionT collection, unsigned size)
{
return find_if(collection, collection + size,
bind2nd(greater<double>(), value)) - collection - 1;
}
template <>
struct BinTraits<LARGE>
{
int get_bin(double value) { return get_bin_impl(value, binning_LARGE, sizeof(binning_LARGE) / sizeof(binning_LARGE[0])); }
};
template <>
struct BinTraits<BE>
{
int get_bin(double value) { return get_bin_impl(value, binning_BE, sizeof(binning_BE) / sizeof(binning_BE[0])); }
};
Then I'd put the actual container behaviour in another class that requires binning behaviour (lets call it HashTable):
template <typename BinTraits>
class HashTable
{
public:
void insert(double value)
{
int bin = BinTraits::get_bin(value);
_bins[bin].insert(value);
}
// _bin is a multimap or something
};
Looking at the usage of find_if and bind2nd as well as functors, it seems as if you are quite knowledgeable about STL and some advanced C++ concepts; yet, what you are trying to do seems to be over-engineering. While I can't fully understand what you are trying to do but it seems that you could do away with templates completely and use just a class (instantiated with different values) and method parameters.

Dynamic data type choosing based on template

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 I understand your question correctly, you want a struct for compile time usage and runtime usage as well with preferably same name. In my opinion, you can declare the class as template and then specialize one of its instance (say size_t = 0xffffffff), which you may not be using. You can declare all your definitions for runtime usage in that instance.
For example,
template<std::size_t dim = ~0> // choose default dimension(0xffffffff) not to be used
class Spline {
public:
Spline () {}
vec::fixed<dim> operator () (double const t) const {}
};
template<>
class Spline<~0> { // specialize the default dimension for runtime use
public:
Spline (std::size_t const dim) {}
vec operator () (double const t) const {}
};
It can be used as below:
Spline<5> o5; // compile time dimensions
Spline<> o0(3); // run time dimensions (don't mention anything in template)
You can just overload it. Making a non-duplicate implementation, however, is a problem with no generic solution, unless you have more template magic that can do this.

Templated Vector and Colour Maths library (Specialisation)

I have created a maths library that operates via templates, it allows the user to specify the size and type of the array within a class which is then used to create a maths vector of any dimension up to four. As soon as I went to create a colour class, it struck me how similar the vector and colour class are. Is there anyway in which I could reduce code reuse and use some form of inheritance or specialisation to separate:
Specific functionality (ie vector3 does not have a setXYZW() function, instead only a setXYZ()) to the dimension of which it can only be used in.
Colour class and vector class can both (in terms of array data member) be of size ranging from 1 to 4 and the both share the same operators, but differ in their use in some circumstances such as a multiply vector differs from a multiply colour.
My knowledge of templates is not that good, so I would very much appreciate if anyone can show me the best solution to such a situation?
template < std::size_t N = 3, typename T = float >
class Vector
{
typedef T Degree, Radian;
private:
T m_vecEntry[N];
public:
// arithmetic operations
Vector operator + (const Vector & _vector) const;
Vector operator - (const Vector & _vector) const;
Vector operator * (const Vector & _vector) const;
Vector operator * (float _val) const;
};
template < std::size_t N = 4, typename T = float >
class Colour
{
private:
T m_colEntry[N];
public:
// arithmetic operations
Colour operator + (const Colour& _colour) const;
Colour operator - (const Colour& _colour) const;
Colour operator * (const Colour& _colour) const;
Colour operator * (float _val) const;
};
Your classes have a fair amount of duplicated code, it is advisable that you do something about it. A possible solution follows.
First, you take the common functionality to a base class:
template <class Derived, std::size_t N, typename T>
class VectorBase
{
protected:
VectorBase() {} // Prevent instantiation of base
Derived operator + (const Derived & _vector) const {
std::cout << "Base addition\n";
return Derived();
}
Derived operator * (T _val) const {
std::cout << "Base scalar multiplication\n";
return Derived();
}
T m_components[N];
};
Then you derive from it your Vector and Colour classes. In each derived class you use using Base::operation; to state explicitly that the corresponsing operation from the base class makes sense in the derived class.
For operations that don't make sense in the derived class you provide an alternative definition or not provide it at all (it will not be accessible since you didn't write using).
You can also add operations that were not in the base class, like Vector::norm:
template < std::size_t N = 3, typename T = float >
class Vector : VectorBase<Vector<N, T>, N, T>
{
typedef VectorBase<Vector<N, T>, N, T> Base;
typedef T Degree, Radian;
public:
using Base::operator+; // Default implementation is valid
using Base::operator*; // Default implementation is valid
T norm() const { // Not present in base class
return T();
}
};
template < std::size_t N = 4, typename T = float >
class Colour : VectorBase<Colour<N, T>, N, T>
{
typedef VectorBase<Colour<N, T>, N, T> Base;
public:
using Base::operator+; // Default implementation is valid
Colour operator * (T _val) const { // Redefines version in base class
std::cout << "Colour scalar multiplication\n";
return Colour();
}
};
The only trick in this code is that I've used the CRTP to make base class operations work with derived types.
Here is a little test program:
int main()
{
Vector<> va, vb;
va + vb;
va.norm();
va * 3.0;
Colour<> ca, cb;
ca + cb;
ca * 3.0f;
}
It prints:
Base addition
Base scalar multiplication
Base addition
Colour scalar multiplication
Ultimately the compiler will only create the parts of the template specialization it determines you are going to use. So it in affect will do the optimization for you e.g. not creating an unused method and so on.
So you may just want to consider making normal pre-processor macros to wrap the slight tweaks per template.
But obviously if you want to make some specializations you can do that too, but you'll still end up duplicating lines of code as it were ;)
A lot of graphic engines keep the two separate for precisely the reasons you mentioned. While the structure of the data is equal both require different semantics for operations on the data. This also has the added benefit of more meaningful function names (setX vs setRed) but means code duplication.
Your implementation is just a wrapper around fixed size arrays. You could move the data and shared functionality in a (possible abstract) base class and provide the specific functionality in child classes.
Another way would be to treat your vector and colour classes as decorators to an array wrapper. Write or use a wrapper around arrays and combine it with vector/color functionality through composition.