/*
* Some examples of contrived MPL usage.
*
*
* James Brotchie 2011 - brotchie@gmail.com
*/
#include <iostream>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/count.hpp>
#include <boost/mpl/unique.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/map.hpp>
#include <boost/mpl/has_key.hpp>
#include <boost/mpl/pair.hpp>
#include <boost/mpl/assert.hpp>
using namespace boost::mpl;
using boost::is_same;
class basebase {
public:
basebase(std::string name) : _name(name) {};
std::string getName() const {
return _name;
}
protected:
std::string _name;
};
class stringbase : public basebase {
public:
stringbase() : basebase("String Base") {};
};
class intbase : public basebase {
public:
intbase() : basebase("Int Base") {};
};
/* Map that allows us to choose the most appropriate
base class for a given type. */
typedef map< pair<int, intbase>,
pair<long, intbase>,
pair<std::string, stringbase>> basemap;
template <typename T>
struct printer : public at<basemap, T>::type {
/* Ensure that T is actually in basemap. */
BOOST_MPL_ASSERT((has_key<basemap, T>));
};
int main() {
/* mpl::vector containing 6 types with duplicate long. */
typedef vector<short, std::string, long, long, double> types;
/* Use types as an iterator, deref the first element.
i1 is of type sort. */
deref<begin<types>::type>::type i1 = 5;
/* Access the second element of types by incrementing using
next, then dereferencing.
s1 is of type std::string. */
deref<next<begin<types>::type>::type>::type s1 = "Hello World";
/* Do the same as above but directly access elemnts 0 and 1 of
the mpl::vector. */
at_c<types, 0>::type i2 = 5;
at_c<types, 1>::type s2 = "Hello World";
typedef pair<int, long> test;
first<test>::type i3 = 15;
second<test>::type i4 = 15;
/* Get rid of duplicates from types vector. */
typedef unique<types, is_same<_1, _2>>::type unique_types;
/* Count how many longs are in the original types vector,
then count how many are in the 'uniqued' vector. */
std::cout << count<types, long>::value << std::endl;
std::cout << count<unique_types, long>::value << std::endl;
/* Construct printer instances for int and std::string. */
printer<int> pi;
printer<std::string> ps;
/* De-commenting this will cause a compile time assert,
because there's no 'double' key in basemap. */
//printer<double> pd;
std::cout << pi.getName() << std::endl;
std::cout << ps.getName() << std::endl;
return 0;
}