@
tition
helios is talking about TMP which is an almost entirely different game to ordinary templates.
boost::mpl
is a meta-programming library, and IMO is rather clever.
I like the way it takes advantage of C++ expressive type system.
For example, take a class for a circular arc. There are lots of ways to construct one using various combinations of the centre point, the radius, various points on the arc, angles for begin and end points, and an arc length. To overload functions, we need different types for these things. Rather than manually create different types in the normal way, I used
boost::mpl::int
to make it easier to create some types:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
#ifndef NAMEDTYPE_HPP
#define NAMEDTYPE_HPP
#include <boost/mpl/int.hpp>
namespace mpl = boost::mpl;
//TheTypes Section
using Radius = mpl::int_<1>;
using BeginAngle = mpl::int_<2>;
using EndAngle = mpl::int_<3>;
using ArcLength = mpl::int_<4>;
using EastOrdinate_t = mpl::int_<5>;
using NorthOrdinate_t = mpl::int_<6>;
using Point2D_t = mpl::int_<7>;
using ArcBeginPoint2D_t = mpl::int_<8>;
using ArcMidPoint2D_t = mpl::int_<9>;
using ArcEndPoint2D_t = mpl::int_<10>;
using CentrePoint2D_t = mpl::int_<11>;
// T is double or better,
// TheType is one of the above in TheTypes Section
template < typename TheType , typename T = double>
class NamedType
{
public:
explicit NamedType(T x = 0.0)
: m_value(x)
{}
NamedType(const NamedType& other) : m_value(other.m_value){}
NamedType& operator= (const NamedType& other) {
// A& operator=(A other) {
// std::cout << "copy assignment of A\n";
// std::swap(n, other.n);
// std::swap(s1, other.s1);
// return *this;
std::swap(m_value, other.m_value);
return *this;
}
T operator()() const {
return m_value;
}
void operator()(T arg) {
m_value = arg;
}
T get_value() const { return m_value; }
private:
T m_value;
};
#endif // NAMEDTYPE_HPP
|
I overloaded the
operator()
to make it easier to set or retrieve the value.
So I was able to successfully test function overloading with these functions, note the underlying types are similar, either double or a Point:
1 2 3
|
void TestOL(Radius_t Radius, BeginAngle_t BeginAng, EndAngle_t EndAngle);
void TestOL(BeginAngle_t BeginAngle, EndAngle_t EndAngle, Radius_t Radius);
void TestOL(EndAngle_t EndAngle, Radius_t Radius, BeginAngle_t BeginAngle);
|
It's contrived: the arguments are just in a different order, I only wanted to test the overloading.
I have use for this in other applications where I have dozens of different types of Distances, Angles, Points (World) and Vectors (deltaX, deltaY), their underlying type is
double
. So now this is much easier to have a header file with a bunch of one liners for all the types I want. This is much better than creating lots of struct's and avoids any inheritance.
Another thing I have been playing with, is to try and get all this working with
boost::quantity
. Not sure how that is going to work out: I have copied one of the examples and added an extra template parameter to everything, but it may not work with the internal templates of the library, because not are not expecting an extra parameter. Not sure about that though.