Subclass a template class with operators - c++

I'm trying to create classes for mathematical vectors in various dimensions, and since they have much in common I created a templated base class with the vectors size as the template parameter. I'm subclassing because I want different constructors (e.g. Vec2f(float x, float y), Vec3f(float x, float y, float z)) and additional functions like the cross product for 3 dimensional vectors.
My Problem: What should operator+ in the baseclass return? If it returns an instance of the baseclass then Vec3f + Vec3f returns Vecnf, but it should return Vec3f. Can this be achieved somehow?
Here is a code example:
template <size_t n>
class Vecnf {
public:
Vecnf operator+(Vecnf const & vec) const {
return Vecnf(*this) += vec;
}
Vecnf & operator+=(Vecnf const & vec) {
for (int i = 0; i < n; ++i) {
elements[i] += vec.elements[i];
}
return *this;
}
protected:
std::array<float, n> elements;
};
class Vec3f : public Vecnf<3> {
public:
Vec3f(float x = 0.0f, float y = 0.0f, float z = 0.0f);
Vec3f crossProd(Vec3f const & vec);
};
With this implementation, the following:
Vec3f a, b;
Vec3f c = a + b;
gives the compile time error
error: conversion from 'Vecnf<3u>' to non-scalar type 'Vec3f' requested
I'm using TDM GCC version 4.8.1 on Windows 8 Pro. I'm using c++11, so your solution can use it as well, but since I don't think it's crucial I haven't flagged the question with it. Thank you in advance :)

You could make the constructor a variadic template, thereby solving your first problem and eliminating the need to even use inheritance:
template <size_t n>
class Vecnf
{
std::array<float, n> elements;
public:
template <typename ... Args>
Vecnf(Args ... args):
elements {{static_cast<float>(args)...}}
{}
// other methods, operators etc...
};
Now you can make typedef's for the commonly used sizes if you like:
typedef Vecnf<3> Vec3f;
In my opinion, you could even improve this by adding another template parameter for the type you want to store in the array. It could default to float of course.
Also, it shouldn't be too hard to implement the cross-product in a generic way...

You can just define an operator+ on vec3f that does what you want it to. It can have a differing return type to vecnf's as long as it's a subtype of it and it will still override it.
Better solution is what #JorenHeit introduced; that actually is what you wanted, together with two typedefs. This solution is c++03 compatible though, and his isn't.

Related

Member field aliases in derived class (no accessor functions)

Toy example:
template<typename T, std::size_t N>
class static_vector
{
public:
T& operator[](std::size_t i) { return m_elements[i]; }
T const& operator[](std::size_t i) const { return m_elements[i]; }
private:
std::array<T, N> m_elements;
};
template<typename T>
class vector3
: public static_vector<T, 3>
{
public:
using vector_type = static_vector<T, 3>;
// x = vector_type::operator[](0);
// y = vector_type::operator[](1);
// z = vector_type::operator[](2);
};
Let vector3<float> pos;. I want to access pos[0] via pos.x. Clearly, if pos is declared to be const, I want pos.x to be read-only.
Is this possible?
Let me stress the fact that I don't want to use accessor functions of the form
T& x() { return (*this)[0]; }
T const& x() const { return (*this)[0]; }
There is no zero cost way to do this using the exact syntax you want.
Relaxing either cost (compile, maintenance, memory usage and runtime) or syntax (which your () is an example of) gets you what you want.
I added a comment to your question but I thought I'd add an answer with some code to clarify. Be warned, what follows is not a good idea.
You can use simple pointer arithmetic to interpret members of a struct as if they were elements in an array. Because the type of the struct members and the type of elements in the pseudo array are the same, we're safe to reinterpret one as the other with the caveat that there is no padding in between the struct members.
The C++ standard gives no method for defining padding in a struct so you will have to rely on compiler specific directives. I believe however that both MSVC and GCC support #pragma pack.
#pragma pack(push, 1)
template <typename T>
struct Vec3
{
T x;
T y;
T z;
T& operator[](size_t i) { return *(&x + i); }
const T& operator[](size_t i) const { return *(&x + i); }
};
#pragma pack(pop)
So why isn't this a good solution?
You are relying on compiler specific directives making your code less portable.
You need to explicitly declare each member which means you'll need separate templates for Vec2, Vec3 and Vec4.
1 byte alignment isn't supported on all architectures again making your code less portable.
Even on architectures where unaligned memory access is supported (such as x86,) it comes with a performance penalty.

C++ Overload index operator for more than one array/vector

I'm not an advanced programmer. How can I overload the [] operator for a class that has two (or more) array/vector type variables?
class X
{
protected:
std::vector<double> m_x, m_y;
public:
double& operator[](const short &i) { return ???; }
};
What should I use for ???, or how can I do it (maybe adding other definitions?) to be able to call either variable?
Additional question: will this allow other classes of type class derived : public X access m_x and m_y for writing?
UPDATE:
Thank you everyone who answered, but I'm afraid that if I draw the line then the answer to my first question is no, and to the second yes. The longer version implies either an extra struct, or class, or plain setters/getters, which I wanted to avoid by using a simple function for all.
As it stands, the current solution is a (temporary) reference to each variable, in each class to avoid the extra X:: typing (and keep code clear), since m_x would have existed, one way or another.
you can write just a function for this, like:
double &get(unsigned int whichVector, unsigned int index)
{
return (whichVector == 0 ? m_x[index] : m_y[index]);
}
or use operator():
struct A
{
std::vector<int> a1;
std::vector<int> a2;
int operator()(int vec, int index)
{
return (vec == 0 ? a1[index] : a2[index]);
}
};
A a;
auto var = a(0, 1);
but still, this is kinda strange :) probably you should just give a const ref outside, like:
const std::vector<double> &getX() const { return m_x; }
and second question: protected will be convert into private in public inheritance (child/derived will have access to these memebers)
Assuming you want m_x and m_y indexed against the same parameter and a single return value:
struct XGetter
{
double& x;
double& y;
};
XGetter operator[](const short &i) { return { m_x[i], m_y[i] }; }
And the const overload:
struct XGetterReadOnly
{
double x;
double y;
};
XGetterReadOnly operator[](const short &i) const { return { m_x[i], m_y[i] }; }
The compiler will make a good job of optimizing away the intermediate classes XGetter and XGetterReadOnly where appropriate which maybe hard to get your head round if you're a new to C++.
If using mixin doesn't make you uncomfortable you could use tag dispatching like:
#include <utility>
#include <vector>
#include <iostream>
template <size_t I>
struct IndexedVector {
std::vector<double> v;
IndexedVector():v(10){}
};
template <size_t I>
struct tag {
int i;
};
template <size_t S, class = std::make_index_sequence<S>>
struct MixinVector;
template <size_t S, size_t... Is>
struct MixinVector<S, std::index_sequence<Is...>>: IndexedVector<Is>... {
template <size_t I>
double &operator[](tag<I> i) {
return IndexedVector<I>::v[i.i];
}
};
int main() {
MixinVector<2> mv;
mv[tag<0>{0}] = 1.0;
std::cout << mv[tag<0>{0}] << std::endl;
}
To use std::index_sequence you need however compiler supporting c++14 (you could though implement it yourself in c++11). The approach is easily expandable to any number of vectors by simple MixinVector template parameter modification.
There are many broken things, either at conceptual and design level.
Are you able to point your finger simultaneously against two distinct things? No? That's why you cannot use one index to address two distinct vector retaining their distinction.
You can do many things: whatever way to "combine" two value int one is good
by a syntactic point of view:
return m_x[i]+m_y[x] or return sin(m_x[i])*cos(m_y[i]) or return whatever_complicated_expression_you_like_much
But what's the meaning of that? The point is WHY THERE ARE TWO VECTOR IN YOUR CLASS? What do you want them to represent? What do you mean (semantically) indexing them both?
Something I can do to keep their distinction is
auto operator[](int i) const
{ return std::make_pair(m_x[i],m_y[i]); }
so that you get a std::pair<double,double> whose fist and second members are m_x[i] and m_y[i] respectively.
Or ... you can return std::vector<double>{m_x[i],m_y[i]};
About your other question: Yes, inheriting as public makes the new class able to access the protected parts: that's what protected is for.
And yes, you cam R/W: public,protected and private are about visibility, not readability and writeability. That's what const is about.
But again: what does your class represent? without such information we cannot establish what make sense and what not.
Ok, stated your comment:
you need two different funcntions: one for read (double operator[](unsigned) const) and one for write (double& operator[](unsigned) const)
If you know vectors have a known length -say 200-, that you can code an idex transforamtion like i/1000 to identify the vector and i%1000 to get the index,so that 0..199 addres the first, 1000..1199 address the second 2000..2199 address the third... etc.
Or ... you can use an std::pair<unsigned,unsigend> as the index (like operator[](const std::pair<unsigned,unsigned>& i), using i.first to identify the vector, and i.second to index into it, and then call x[{1,10}], x[{3,30}] etc.
Or ... you can chain vetor together as
if(i<m_x.size()) return m_x[i]; i-=m_x:size();
if(i<m_y.size()) return m_y[i]; i-=m_y:size();
if(i<m_z.size()) return m_z[i]; i-=m_z:size();
...
so that you index them contiguously.
But you can get more algorithmic solution using an array of vectors instead of distinct vector variables
if you have std::array<std::vector<double>,N> m; instead of m_x, m_y and m_z the above code can be...
for(auto& v: m)
{
if(i<v.size()) return v[i];
i-=v.size();
}
You can return a struct has two double
struct A{
double& x;
double& y;
A(A& r) : x(r.x), y(r.y){}
A(double& x, double& y) : x(x), y(y){}
};
class X
{
protected:
std::vector<double> m_x, m_y;
public:
A operator[](const short &i) {
A result(m_x[i], m_y[i]);
return result;
}
};
Thank for editing to #marcinj

Declare member function only for specific template instantiation of class

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?

Optional structural typing possibility in C++ or any other language?

In C++ how to tell compiler that Ogre::Vector3 IS_SAME_AS SomeOtherLIB::Vector3 ?
I feel that.. in languages like c++ which are not structural typed but there are cases when it makes sense.
Normally as game developer when working with 4+ libraries that provide sort or their own Vector3 implementation. The code is littered with ToOgre, ToThis, ToThat conversion function. Thats a lot of Float3 copying around which should not happen on first place.
Is in C++ or any other languages where we dont have to convert (copying) from one type to another which is essentially the samething. But any solution in C++ as most of the good gamedevs libs are for c/c++.
If you use templates you can define functions that take any type of argument as long as the necessary operations are defined on that type. Example:
class Foo { void quack() {} };
class Bar { void quack() {} };
class Baz {};
template<typename Duck>
void f(Duck d) {
d.quack();
}
int main() {
f(Foo()); // works
f(Bar()); // works
f(Baz()); // compile error because Baz does not have a quack method
return 0;
}
While it doesn't suit any situation, templates can give you "compile-time duck typing".
Lets say you have two vector types:
struct Vec3A {
float x, y, z;
};
struct Vec3B {
float p[3];
};
You can define function templates that hide the implementation how of to get the components:
template<class T> float get_x(const T&);
template<class T> float get_y(const T&);
template<class T> float get_z(const T&);
template<> float get_x<Vec3A>(const Vec3A& v) { return v.x; }
// ...
template<> float get_x<Vec3B>(const Vec3B& v) { return v.p[0]; }
// ...
With such helpers you can now write generic functions that work on both:
template<class T> float length(const T& t) {
return std::sqrt(std::pow(get_x(t), 2),
std::pow(get_y(t), 2),
std::pow(get_z(t), 2));
}
You can also continue by specializing utilities like length() for performance or other reasons, e.g. if a certain vector already has a member function providing you with the length:
template<> float length<Vec3C>(const Vec3C& v) {
return v.length();
}
If you are really sure in case of non-virtual structures, you can do a reinterpret_cast. However, it's better to:
do templated wrapper functions as shown by sepp2k
inherit from one of the vectors and add a conversion operator to the other vector
add a separate _cast function that does the conversion
Haxe is a highly portable language with completely optional structural subtyping:
typedef Vector3 = { x : double, y : double, z : double };
class FancyVector3 {
public var x : double, y : double, z : double;
function dot(Vector3 v) {
return x * v.x + y * v.y + z * v.z;
}
function length() {
return Math.sqrt(dot(this));
}
}
Not only is Vector3 an already usable structure, it also acts as a structural interface for other classes. Such typedef'd structs can specify function signatures as well as fields.
Haxe also has a CFFI for talking to C++ (although it still requires conversion methods), and bindings already exist for a few C++ game engines, as well as a variety of lower-level frameworks. Cross-platform engines written in pure Haxe are also being developed, targeting variously C++, Flash, and JS (both Canvas and WebGL).
This is probably not the solution you are looking for right now, but may become more interesting within a few years.

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.