Calling the appropriate function based on an enumeration, but using templates - c++

I have this wrapper function that is supposed to call the appropriate function on a large dataset based on the type of data it contains, like this:
void WrapperFunc( int iRealDataType, int iUseAsDataType )
{
// now call the right function based on both arguments
switch ( iRealDataType )
{
case FancyType1:
switch ( iUseAsDataType )
{
case CoolType1: DataAnalysisFunc_Fancy1_Cool1(); break;
// etc.
}
// etc.
}
}
So far, this was solved by having two nested switch statements and then calling one of the many many specialized functions for each existing combination of Real and UseAs data type. However as the number of defined types grows it is a nightmare to maintan the code base. So I decided to finally use templates. I mostly avoid them if I can, but this time they suit the problem well.
So now instead of DataAnalysisFunc_Fancy1_Cool1 i would like to call DataAnalysisFunc<FancyType1,CoolType1> ang get rid of the hundreds of lines of switch statements, BUT i cannot use it like this, since FancyType1 is an enum, not the type (which is Fancy1 for example).
Just to clarify - I know this sounds like a stupid artificial example, but I tried to simplify the problem as much as possible to get to the core of it, instead of explaining the ton of details that would go into a much more concrete example.
EDIT: my data analysis functions are in reality CUDA kernels - this will probably rule out some possible solutions. Sorry for that.

Templates sound like the wrong solution. What you want is a lookup table.
typedef void (*DataAnalysisFunc)();
const DataAnalysisFunc DataAnalysisFunctions[NumFancyTypes][NumCoolTypes] = {
/*Fancy1*/ {
/*Cool1*/ &DataAnalysisFunc_Fancy1_Cool1,
/*Cool2*/ &DataAnalysisFunc_Fancy1_Cool2 }
/*Fancy2*/ {
/*Cool1*/ &DataAnalysisFunc_ImpossibleCombination, // can't happen, throw or something
/*Cool2*/ &DataAnalysisFunc_Fancy2_Cool2 }
};
void WrapperFunc(int realDataType, int useAsDataType) {
assert(realDataType >= 0 && realDataType < NumFancyTypes);
assert(useAsDataType >= 0 && useAsDataType < NumCoolTypes);
(*DataAnalysisFunctions[realDataType][useAsDataType])();
}
Now, if those DataAnalysisFuncs share a lot of code, templates might help you there, but not for dynamic dispatch.

BUT i cannot use it like this, since FancyType1 is an enum, not the
type (which is Fancy1 for example)
You can convert enum to type, just use one of metaprogramming basic tools:
Int2Type, it is used to replace run-time branches of if statements on the compile time dispatches.
It looks like:
template <int Number>
struct Int2Type
{
enum {value};
};
Int2Type - is treated as a type, using it and function overloading - you can replace if statements.
UPDATE:
I added some example here, to make my answer more clear
1. Int2Type
// usage allows to implement dispatch in a compile time instead of branching statements in a run-time
template <int Val>
struct Int2Type
{
static const int val_= Val;
};
template <typename ItBegin, typename ItEnd>
void doSort(ItBegin it0, ItEnd it1, Int2Type<1>)
{
using namespace std;
// sort
cout << "Standart sorting algorithm was used. For iterators" << endl;
}
template <typename ItBegin, typename ItEnd>
void doSort(ItBegin it0, ItEnd it1, Int2Type<2>)
{
using namespace std;
// sort
cout << "Fast sorting algorithm was used. For pointers" << endl;
}
// based on the 3-rd dummy type parameter call will be dispatched to needed function
int arr[3];
MainTools::doSort(arr, arr + sizeof(arr) / sizeof(arr[0]), MainTools::Int2Type<1>());
vector<int> v(3);
MainTools::doSort(v.begin(), v.end(), MainTools::Int2Type<2>());

You're looking for type dispatching. I find this easiest to do with Boost.MPL.
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/at.hpp>
struct DispatchChecker
{
int iRealDataType, iUseAsDataType;
template <class T>
void operator()(T) const
{
static const int iCurrentReal = boost::mpl::at_c<T, 0>::type::value;
static const int iCurrentUseAs = boost::mpl::at_c<T, 1>::type::value;
if(iRealDataType == iCurrentReal &&
iUseAsDataType == iCurrentUseAs)
DataAnalysisFunc<iCurrentReal,iCurrentUseAs>();
}
};
typedef /*mpl sequence of all valid types*/ valid_types;
boost::mpl::for_each<valid_types>(DispatchChecker{iRealDataType,iUseAsDataType});
boost::mpl::for_each accepts a compile time sequence and instantiates and runs a functor on each element of the sequence. In this case the functor checks that the compile parameters match the runtime parameters and calls the appropriate DataAnalysisFunc when they match.
As for how to get the valid_types, the easiest way is to just write out each valid pair in a sequence like this:
typedef boost::mpl::vector<
boost::mpl::vector_c<int, 0, 0>,
boost::mpl::vector_c<int, 2, 0>,
boost::mpl::vector_c<int, 1, 1>,
boost::mpl::vector_c<int, 0, 2>,
boost::mpl::vector_c<int, 1, 2>
> valid_types;
Note:
As Sebastian Redl points out, using templates is probably only worthwhile if the DataAnalasysFuncs share a lot code between them, otherwise a runtime dispatch is probably a much better solution.

Related

How to define a vector of functions that accepts different parameter types in c++?

I am doing a challenge for myself and writing a program in C++ without using classes and class related machinery. Additional conditions are I can use everything from stl and have full type safety, meaning no raw pointers or casting from one type to another. I am now in a situation where I'm not sure how to proceed with the constraints I have put on myself.
Problem: I want to create a std::vector of functions, but each of those functions might take a different data type, and operate on that type only. Example:
struct DataAndFunction {
AnyDataType data;
std::function<void(AnyDataType&)> functionOperatingWithData;
};
...
std::vector<DataAndFunction> listOfFunctions;
...
for(auto& dataAndFunc : listOfFunctions) {
dataAndFunc.functionOperatingWithData(dataAndFunc.data);
}
then there either would be different kind of AnyDataType and accompanying functions.
I know it could be solved in a couple of ways:
with classes using polymorphism, where
std::vector< DataAndFunction > listOfFunctions;
would just take a base class as a template parameter, and would have virtual method, that would be implemented by child classes, each with their own private data members, but the point of my challenge is to not use this pattern.
I could pass void* as data and function signature, and inside each function I would cast the data to the appropriate type, but I want to use type safety and only smart pointers
I could also make DataAndFunction struct a generic by adding template parameter, but then how do I make a vector that could be filled with not just with of DataAndFunction<int> for example, but any template parameter?
And how would this problem be solved in a more functional style? How would a functional solution look in C++ that would operate on a list of functions each taking a different type of argument? Without using inheritance of course.
Or am I just asking how to emulate a virtual table?
It seems you only need std::function<void()>:
DataAndFunction<int> dint;
DataAndFunction<char> dchar;
std::vector<std::function<void()>> funcs{
[&](){ dint.f(dint.data); },
[&](){ dchar.f(dchar.data); },
[](){ std::cout << "Hello world\n"; }
};
for (auto& f : funcs) {
f();
}
How you know, C++ is a strong typed language. That means you can't have a generic variable like others languages do like Python.
In C, the solution is to use a point to void (void*), but it is hard to manage and error-prone.
C++17 comes with 2 elegant solutions these you can use:
std::any and
std::variant.
This is one way you could store a vector of functions that take different types as parameters, it also accepts a varying amount of parameters. It uses std::any, std::pair, and std::tuple to contain the function and its parameter(s). std::any is much safer than a void * however there is more memory overhead as std::any stores quite a bit of data.
the program simply outputs : "Hello World!"
#include <any>
#include <tuple>
#include <string>
#include <vector>
#include <utility>
#include <iostream>
#include <functional>
std::vector<std::pair<std::function<void(const std::any&)>, std::any>> funcList;
template <typename F, typename...T>
std::size_t insertAnyFunc(const F &func, const T&...params) {
auto t = std::make_tuple<const T&...>(params...);
funcList.push_back({
[f = func](const std::any &a) {
if constexpr (sizeof...(T) == 0)
f();
else
std::apply(f, std::any_cast<const std::tuple<T...> &>(a));
}, std::make_any<std::tuple<T...>>(t)
});
return funcList.size();
}
void execAnyFunc(const std::size_t &ID) {
if (ID < funcList.size())
funcList.at(ID).first(funcList.at(ID).second);
}
int main (void) {
insertAnyFunc([](const std::string &s){ std::cout << s; }, std::string("Hello World!\n"));
execAnyFunc(0);
return 0;
}

Static duck typing in C++

C++ has some sort of duck typing for types given by template parameters. We have no idea what type DUCK1 and DUCK2 will be, but as long as they can quack(), it will compile and run:
template <class DUCK1, class DUCK2>
void let_them_quack(DUCK1* donald, DUCK2* daisy){
donald->quack();
daisy->quack();
}
But it's a bit inconvenient to write. When I do absolutely not care what actual types DUCK1 and DUCK2 are but rather want to fully use the idea of duck typing, then I would like to have something sligthly different than above:
I'd like to omit writing a template parameter list that is repetitive and mostly meaningless (Just imagine what would happen if there are 7 ducks...)
I'd like to make it a bit more explicit that the types are never used and that it's only the interface that matters.
I'd like to have sort of an interface annotation/check. Make somehow clear what interface is expected behind the type. (That's, however, a bit in contrast of duck typing.)
Does C++ offer any features to achieve one or more of the 3 ideas?
(I know that virtual inheritance is the method of choice in most cases to implement such patterns, but the question here is specifically about the case of static polymorphism.)
Concerning questions 1 and 2: since C++14 you can omit explicit template <typename ... boilerplate and use auto, but only in lambdas:
auto let_them_quack = [] (auto & donald, auto & daisy){
donald.quack();
daisy.quack();
};
(yes, I prefer references to pointers). GCC allows to do so in usual functions as an extension.
For the question 3, what you are talking about are called concepts. They existed in C++ for a long time, but only as a documentational term. Now the Concepts TS is in progress, allowing you to write something like
template<typename T>
concept bool Quackable = requires(T a) {
a.quack();
};
void let_them_quack (Quackable & donald, Quackable & daisy);
Note that it is not yet C++, only a technical specification in progress. GCC 6.1 already seems to support it, though. Implementations of concepts and constraints using current C++ are possible; you can find one in boost.
I'd like to omit writing a template parameter list that is repetitive
and mostly meaningless (Just imagine what would happen if there are 7
ducks...)
For that you could use variadic templates and do something like the following:
template<typename DUCK>
void let_them_quack(DUCK &&d) {
d.quack();
}
template<typename DUCK, typename... Args>
void let_them_quack(DUCK &&d, Args&& ...args) {
d.quack();
let_them_quack(std::forward<Args>(args)...);
}
Live Demo
#2 and #3 are sort of taken care of by the fact that the code will not compile, and throw a compilation error, if the given classes don't implement the interface. You could also make this formal:
class duck {
public:
virtual void quack()=0;
};
Then declare the parameters to the function as taking a pointer to a duck. Your classes will have to inherit from this class, making the requirements for let_them_quack() crystal clear.
As far as #1 goes, variadic templates can take care of this.
void let_them_quack()
{
}
template <typename ...Args>
void let_them_quack(duck* first_duck, Args && ...args) {
first_duck->quack();
let_them_quack(std::forward<Args>(args)...);
}
You will be able to make it look preetier with concept (not yet in standard - but very close):
http://melpon.org/wandbox/permlink/Vjy2U6BPbsTuSK3u
#include <iostream>
template<typename T>concept bool ItQuacks(){
return requires (T a) {
{ a.quack() } -> void;
};
}
void let_them_quack2(ItQuacks* donald, ItQuacks* daisy){
donald->quack();
daisy->quack();
}
struct DisneyDuck {
void quack(){ std::cout << "Quack!";}
};
struct RegularDuck {
void quack(){ std::cout << "Quack2!";}
};
struct Wolf {
void woof(){ std::cout << "Woof!";}
};
int main() {
DisneyDuck q1, q2;
let_them_quack2(&q1, &q2);
RegularDuck q3, q4;
let_them_quack2(&q3, &q4);
//Wolf w1, w2;
//let_them_quack2(&w1, &w2); // ERROR: constraints not satisfied
}
output:
Quack!Quack!Quack2!Quack2!
As you can see, you will be able to: omit writing a template parameter list, ItQuacks is quite explicit so types are never used and that it's only the interface that matters takes place. This I'd like to have sort of an interface annotation/check. also takes place, concept use will also give you meaningfull error message.
We only need to write one version of the function:
#include <utility>
template<typename... Quackers>
void let_them_quack(Quackers&& ...quackers) {
using expand = int[];
void(expand { 0, (std::forward<Quackers>(quackers).quack(), 0)... });
}
struct Duck {
void quack() {}
};
int main()
{
Duck a, b, c;
let_them_quack(a, b, c, Duck());
}

Optimize template replacement of a switch

I have a lot of custom datatypes in one of my projects which all share a common base class.
My data (coming from a database) has a datatype which is distinguished by an enum of the base class. My architecture allows a specific datatype to be specialized with a derived class or it can be handled by the base class.
When I construct one my specific datatypes I normally call the constructor directly:
Special_Type_X a = Special_Type_X("34.34:fdfh-78");
a.getFoo();
There is some template magic which also allows constructing it like this:
Type_Helper<Base_Type::special_type_x>::Type a = Base_Type::construct<Base_Type::special_type_x>("34.34:fdfh-78");
a.getFoo();
For some values of the type enum there might be no specialization so
Type_Helper<Base_Type::non_specialized_type_1>::Type == Base_Type
When I'm fetching data from the database the datatype isn't known at compile time so there's a third way to construct the datatypes (from a QVariant):
Base_Type a = Base_Type::construct(Base_type::whatever,"12.23#34io{3,3}");
But of course I want the correct constructor to be called, so the implementation of that method used to look like:
switch(t) {
case Base_Type::special_type_x:
return Base_Type::construct<Base_Type::special_type_x>(var);
case Base_Type::non_specialized_type_1:
return Base_Type::construct<Base_Type::non_specialized_type_1>(var);
case Base_Type::whatever:
return Base_Type::construct<Base_Type::whatever>(var);
//.....
}
This code is repetitive and since the base class can handle new types (added to the enum) as well, I came up with the following solution:
// Helper Template Method
template <Base_Type::type_enum bt_itr>
Base_Type construct_switch(const Base_Type::type_enum& bt, const QVariant& v)
{
if(bt_itr==bt)
return Base_Type::construct<bt_itr>(v);
return construct_switch<(Base_Type::type_enum)(bt_itr+1)>(bt,v);
}
// Specialization for the last available (dummy type): num_types
template <>
Base_Type construct_switch<Base_Type::num_types>(const Base_Type::type_enum& bt, const QVariant&)
{
qWarning() << "Type" << bt << "could not be constructed";
return Base_Type(); // Creates an invalid Custom Type
}
And my original switch statement is replaced with:
return construct_switch<(Base_Type::type_enum)0>(t,var);
This solution works as expected.
The compiled code is however different. While the original switch statement had a complexity of O(1) the new approach results in a O(n) complexity. The generated code recursively calls my helper method until it finds the correct entry.
Why can't the compiler optimize this properly? Are there any better ways to solve this?
Similar problem:
Replacing switch statements when interfacing between templated and non-templated code
I should mention that I would like to avoid C++11 and C++14 and stick to C++03.
This is what I call the magic switch problem -- how to take a (range of) run time values and turn it into a compile time constant.
Abstractly, you want to generate this switch statement:
switch(n) {
(case I from 0 to n-1: /* use I as a constant */)...
}
You can use parameter packs to generate code that is similar to this in C++.
I'll start with c++14-replacing boilerplate:
template<unsigned...> struct indexes {typedef indexes type;};
template<unsigned max, unsigned... is> struct make_indexes: make_indexes<max-1, max-1, is...> {};
template<unsigned... is> struct make_indexes<0, is...>:indexes<is...> {};
template<unsigned max> using make_indexes_t = typename make_indexes<max>::type;
Now we can create a compile-time sequence of unsigned integers from 0 to n-1 easily. make_indexes_t<50> expands to indexes<0,1,2,3, ... ,48, 49>. The c++14 version does so in O(1) steps, as most (all?) compilers implement std::make_index_sequence with an intrinsic. The above does it in linear (at compile time -- nothing is done at run time) recursive depth, and quadratic compile time memory. This sucks, and you can do better with work (logarithmic depth, linear memory), but do you have more than a few 100 types? If not, this is good enough.
Next, we build an array of callbacks. As I hate C legacy function pointer syntax, I'll throw in some pointless boilerplate to hide it:
template<typename T> using type = T; // pointless boilerplate that hides C style function syntax
template<unsigned... Is>
Base_Type construct_runtime_helper( indexes<Is...>, Base_Type::type_enum e, QVariant const& v ) {
// array of pointers to functions: (note static, so created once)
static type< Base_Type(const QVariant&) >* const constructor_array[] = {
(&Base_Type::construct<Is>)...
};
// find the eth entry, and call it:
return constructor_array[ unsigned(e) ](v);
}
Base_Type construct_runtime_helper( Base_Type::type_enum e, QVariant const& v ) {
return construct_runtime_helper( make_indexes_t< Base_Type::num_types >(), e, v );
}
and Bob is your Uncle1. An O(1) array lookup (with an O(n) setup, which in theory could be done prior to your executable launching) for dispatch.
1 "Bob's your Uncle" is a British Commonwealth saying that says "and everything is finished and working" roughly.
Are all the functions inline? I'd expect a reasonable compiler to optimize the if tree into a switch, but only if the ifs are in the same function. For portability, you might not want to rely on this.
You can get O(1) with an indirect function call by having construct_switch populate a std::vector<std::function<Base_Type(const QVariant&)>> with lambda functions that do the construction and then dispatch off that.

Could someone help me create a variable container using Boost::MPL?

I have created a physics system that handles any collision object to any collision object like so:
namespace Collision
{
template <typename T, typename U>
inline void Check(T& t, U& u)
{
if(u.CheckCollision(t.GetCollider()))
{
u.HitBy(t);
t.Hit(u);
}
}
}
and there are several other helper objects to make it easy to use, but the gist is that there are dynamic objects that need to be tested against static objects and other dynamic objects, but static objects don't need to be checked.
What I would like is something like this:
void func()
{
PhysicsWorld world;
shared_ptr<CSphere> ballPhysics(new CSphere(0,0,ballSprite->Width()));
BallCommand ballBehavior;
CBounds bounds(0, 0, 640, 480);
CBox obstacle(200, 150, 10, 10);
Collision::Collidable<CBounds> boundC(bounds);
Collision::Collidable<std::shared_ptr<CSphere>, BallCommand&> ballC(ballPhysics, ballBehavior);
Collision::Collidable<CBox> obstC(obstacle);
world.addStatic(boundC);
world.addDynamic(ballC);
world.addStatic(obstC);
...
...
world.Update();
...
...
}
I'd love to deduce the containers through the add functions so using the system automatically updates the type lists. I think I get how to generate a typelist with a template function, but not how to then get it where I need it, or at what point in compilation it is complete.
If not that then some system using two typelists that then internally writes the update function to iterate through all the lists pairing them up against each other.
I've read some of the boost MPL book and read Andrei's book several times. But, I seem to get caught up in the how it works stuff and don't really translate that into how do I use it. I wish they had one more section on real world examples in the MPL book.
I've been able to get all of the pieces of a game engine to interact with rendering, physics, collisions (I separate detection from reaction), input, network, sound, etc. All in generic ways. Now I just need to hold all the things in a generic way. After all that generic work, it would be silly to require inheritance just so I can hold something in a container and I don't want to hand code every collection possibility as that is one of the great benefits of generic programming.
I saw Jalf had indicated that s/he used MPL to do something similar, but did not go into details enough for me to figure it out. If anyone knows a practical use example or where I can get more info on using the MPL I'd be grateful.
Thanks again!
Update
boost MPL and boost Fusion both seem to do what I want, but there appears to be very little in the way of good real life examples of either libraries. The documentation for MPL is little more than this template does this and good luck understanding the implications of that. Fusion is a bit better with "Here's an example but it's just the tip of the iceberg!"
A typical boost MPL example is has_xxx. They use XXX and xxx in the example making it difficult to see the difference where XXX(The required text) and Test or CheckType or any more distinguishable user type could be used in place of xxx. Plus there is no mention that none of this is in a namespace. Now I know why Scott meyers compared this to the shower scene in Psycho.
It's a shame really because what little I have gotten to compile and understand does really useful things, but is so hard to figure out I would never spend this much effort if I was on a shipping product.
If anyone knows real world examples or better references, explanations, or tutorial I would be grateful.
Update
Here's more code:
template <typename T, typename V = VictimEffect, typename M = MenaceEffect>
class Collidable
{
T m_Collider;
V m_HitBy;
M m_Hit;
public:
Collidable(T collide, V victim, M menace) : m_Collider(collide), m_HitBy(victim), m_Hit(menace) {;}
Collidable(T collide) : m_Collider(collide) {;}
Collidable(T collide, V victim) : m_Collider(collide), m_HitBy(victim) {;}
T& GetCollider()
{
return m_Collider;
}
template <typename V>
void HitBy(V& menace)
{
m_HitBy.HitBy(menace.GetCollider());
}
template <typename V>
void Hit(V& victim)
{
m_Hit.Hit(victim.GetCollider());
}
template <typename V>
bool CheckCollision(V& menace)
{
return m_Collider.CheckCollision(menace);
}
};
Then to use it I do this
Collidable<Boundary, BallCommand> boundC(boundary, ballBehavior);
Collidable<CollisionBox> ballC(circle);
Then all I need is to call collide with all my active collidable objects against all my active and passive objects.
I'm not using std::function because the addition of function names makes the code clearer to me. But maybe that's just legacy thinking.
If I understand correctly your problem is:
class manager {
public:
template<typename T>
void add(T t);
private:
/* ??? */ data;
/* other members? */
};
manager m;
some_type1 s1;
some_type2 s2;
m.add(s1);
m.add(s2);
/* m should hold its copies of s1 and s2 */
where some_type1 and some_type2 are unrelated and you're unwilling to redesign them to use dynamic polymorphism.
I don't think either MPL or Fusion will do what you want with this form. If your problem is what container to use as a member of PhysicsWorld, then no amount of compile-time computations will help: the member type is determined at instantiation time, i.e. the line manager m;.
You could rewrite the manager in a somewhat meta-programing fashion to use it this way:
typedef manager<> m0_type;
typedef typename result_of::add<m0_type, some_type1>::type m1_type;
typedef typename result_of::add<m1_type, some_type2>::type final_type;
/* compile-time computations are over: time to instantiate */
final_type m;
/* final_type::data could be a tuple<some_type1, some_type2> for instance */
m.add(s1); m.add(s2);
This is indeed the sort of things MPL+Fusion can help with. However this still remains quite anchored in the compile-time world: can you imagine writing an template<typename Iter> void insert(Iter first, Iter last) just so you can copy the contents of a container into a manager?
Allow me to assume that your requirements are such that in fact the manager has to be used in a much more runtimey fashion, like in my original formulation of your question. (I don't think that's quite a stretch of the imagination for a PhysicsWorld). There is an alternative, which I think is more appropriate, much less verbose and more maintanable: type-erasure. (The name of the technique may be a bit unfortunate and can be misleading the first time.)
A good example of type-erasure is std::function:
std::function<void()> func;
func = &some_func; /* this just looks like that internally std::function stores a void(*)() */
func = some_type(); /* but here we're storing a some_type! */
Type-erasure is a technique to bridge compile-time with runtime: in both assignments above, the arguments are unrelated types (one of which is non-class so not even remotely runtime polymorphic), but std::function handles both, provided they fulfill the contract that they can be used as f() (where f is an instance of the respective type) and that the expression has type (convertible to) void. The contract here is the compile-time aspect of type-erasure.
I'm not going to demonstrate how to implement type-erasure because there is a great Boostcon 2010 presentation on the subject. (You can watch the presentation and/or get the slides through the link). Or I (or someone else) can do it in the comments.
As a final note, implementation of type-erasure (typically) uses dynamic polymorphism. I mention that because I noticed you considered the use of typelists as a runtime object stored as a manager member. This smells like poor man's reflection, and really, poor man's dynamic polymorphism. So don't do that please. If you meant typelists as in the result of a MPL computation then disregard the node.
This is not complete And I did not get everything I want, but it's good enough for now. I'm entering the whole solution in case it helps others.
#include <boost\mpl\vector.hpp>
#include <boost\mpl\fold.hpp>
#include <boost\mpl\for_each.hpp>
#include <boost\mpl\inherit.hpp>
#include <boost\mpl\inherit_linearly.hpp>
#include <iostream>
#include <vector>
using namespace boost::mpl::placeholders;
typedef boost::mpl::vector<short, long, char, int> member_types;
template <typename T>
struct wrap
{
std::vector<T> value;
};
typedef boost::mpl::inherit_linearly<member_types, boost::mpl::inherit<wrap<_2>, _1> >::type Generate;
class print
{
Generate generated;
public:
template <typename T>
void operator()(T)
{
std::cout << *static_cast<wrap<T>&>(generated).value.begin() << std::endl;
}
template <typename T>
void Add(T const& t)
{
static_cast<wrap<T>&>(generated).value.push_back(t);
}
};
void main()
{
print p;
short s = 5;
p.Add(s);
long l = 555;
p.Add(l);
char c = 'c';
p.Add(c);
int i = 55;
p.Add(i);
boost::mpl::for_each<member_types>(p);
}
This isn't the final object I need, but now I have all the pieces to make what I want.
Update
And finally I get this.
template <typename TL>
class print
{
template <typename T>
struct wrap
{
std::vector<T> value;
};
typedef typename boost::mpl::inherit_linearly<TL, boost::mpl::inherit<wrap<_2>, _1> >::type Generate;
Generate generated;
public:
void Print()
{
boost::mpl::for_each<TL>(*this);
}
template <typename T>
void operator()(T)
{
std::cout << *static_cast<wrap<T>&>(generated).value.begin() << std::endl;
}
template <typename T>
void Add(T const& t)
{
static_cast<wrap<T>&>(generated).value.push_back(t);
}
};
Here TL is a boost::mpl container of what types should be held.
I think that provides a good starting point for expanding, but covers much of the metaprogramming parts.
I hope this helps others.

Examples of practical usage of Boost::MPL?

Can you share any real-world examples of Boost::MPL usage (except lambdas), just to let me better understand its purposes and field of practical usage? The MPL documentation tutorial has a dimensional analysis example, but maybe because it's such an academic example it hasn't given me a feeling of Boost::MPL and when it can be effectively used.
I've used Boost.Mpl to generate variant-like classes.
For example, given a MPL type list such as this:
typedef boost::mpl::set<Foo, Bar, Baz> type_set;
I then use boost::mpl::fold to build a chain of classes derived from each others which each adds an std::unordered_set of one of the types in the type set. The end result is a class which contains an unordered_set<Foo>, an unordered_set<Bar> and an unordered_set<Baz>.
And because the class is specified in terms of a boost::mpl::set, I can iterate over these types to automatically generate other functions as well, such as an operator== which compares all of the unordered_sets.
The fact is, Boost.MPL, like Boost.Preprocessor, are really building blocks.
Most of the times, you probably use it through other libraries, as a number of Boost libraries are built upon those two.
For example:
Boost.Fusion (which crosses the gaps between compile-time and run-time realms)
Boost.MultiIndex (for an easier interface)
Boost.Unit (for dimensional analysis)
Boost.Variant may, I think, also depends on it
You may use it unknowningly already :)
I use a more enhanced dimensional analysis library called Boost.Units.
I've developed a compile-time reflection library and then used that library to build a generic class that provides runtime-reflection to any compile-time reflected type passed in. I've used that support to automatically generate UI components to edit the properties of such reflected types.
It's also paramount to the distribution of events within our application. For instance, when someone changes the units they wish the system to be in, I don't have to teach that system that new items have been added to given devices because the code uses MPL to analyze those types and just knows that something's been added and changes it.
I've just used metaprogramming techniques to wrap up the Qt signals into something that regains the type safety removed by their system and is able to connect with any functional entity.
But to tell the truth, you've almost certainly used practically applied metaprogramming techniques already when you've used standard algorithms like sort. A decent implementation of the sort algorithm uses a less evolved form of metaprogramming to analyze the iterators passed in and then uses tag-dispatching to initiate a sort algorithm capable of fully utilizing the features of those iterators.
Quite frankly, if you're not doing metaprogramming then you're not utilizing the power of C++ and you may as well be using something else.
When it comes to build matching engine, mostly for Exchange or DarkPool in trading area, we usually need to check if 2 orders could match or not (or we say could cross or not), there could be many aspects to check which we call as Rules, and here are the key requirements in term of organizing these rules:
It should be easy to add a new rule and get applied
It should be convenient to organize rules into different groups to apply the checks
Because the rule check are invoked quite frequently - well, of couse, that is the sole job of a matching engine, we want it as optimal as possible
This is a great fit to use boost mpl, which could use compile time sequence boost::mpl::vector to organize rules, and get them applied with boost::mpl::for_each.
The idea is best illustrated with an example:
It is straightforwrad to add a new rule by simply defining a new Rule class
It is convenient to group rules using boost::mpl::vector, and use it as a template parameter for canCross check
Because most of the setting up work are done in compile time, it is fast.
#include <iostream>
#include <vector>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/for_each.hpp>
using namespace std;
struct Order {};
struct Rule1
{
const char* name() const { return "Rule1"; }
bool apply(const Order& a, const Order& b) const { cout << "Checking Rule1..." << endl; return true; }
};
struct Rule2
{
const char* name() const { return "Rule2"; }
bool apply(const Order& a, const Order& b) const { cout << "Checking Rule2..." << endl; return false;}
};
struct Rule3
{
const char* name() const { return "Rule3"; }
bool apply(const Order& a, const Order& b) const { cout << "Checking Rule3..." << endl; return false;}
};
struct Rule4
{
const char* name() const { return "Rule4"; }
bool apply(const Order& a, const Order& b) const { cout << "Checking Rule4..." << endl; return true;}
};
struct RuleApplicator
{
RuleApplicator(bool& success, std::vector<const char*>& failedRules, const Order& order1, const Order& order2):
_success(success),
_failedRules(failedRules),
_order1(order1),
_order2(order2)
{}
template <typename U> void operator() (U rule)
{
if(!rule.apply(_order1, _order2))
{
_success = false;
_failedRules.push_back(rule.name());
}
}
private:
bool& _success;
std::vector<const char*>& _failedRules;
const Order& _order1;
const Order& _order2;
};
template <class Rules>
bool canCross(const Order& a, const Order& b)
{
bool success = true;
std::vector<const char*> failedRules;
RuleApplicator applicator(success, failedRules, a, b);
boost::mpl::for_each<Rules>(applicator);
if (!success)
{
cout << "Can't cross due to rule check failure:";
for(const char* ruleName: failedRules)
{
cout << ruleName << " ";
}
cout << endl;
return false;
}
else
{
cout << "Can cross!" << endl;
return true;
}
}
int main(int argc, char** argv)
{
Order a, b;
canCross<boost::mpl::vector<Rule1, Rule4>>(a, b);
cout << endl;
canCross<boost::mpl::vector<Rule1, Rule2, Rule3, Rule4>>(a, b);
}
You will see output as:
Checking Rule1...
Checking Rule4...
Can cross!
Checking Rule1...
Checking Rule2...
Checking Rule3...
Checking Rule4...
Can't cross due to rule check failure:Rule2 Rule3
If your application has heavy logic in dealing with key-value pairs, you will need a ultra efficent way to get value from key, typical hashmap works well, but if possible keys are known upfront, optimzation could be done use boost::mpl, with an array, and a method to convert your key to array index at compile time, this is certainly more efficent.
Here is an example on handling fix message, which is a message contains various key-value pairs, it is used heavily in financial trading applications:
#include <iostream>
#include <array>
#include <string>
#include <unordered_set>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/find.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/size.hpp>
using namespace std;
using namespace boost;
struct TagEntity
{
bool isValid;
std::string value;
};
template<class CommonTags>
struct FixMsg
{
static constexpr uint32_t CommonTagsCount = mpl::size<CommonTags>::type::value;
template<int Tag>
constexpr uint32_t index()
{
constexpr auto idx = mpl::find<CommonTags, mpl::integral_c<int, Tag>>::type::pos::value; // this is the key step: convert tag to index in compile time
static_assert(idx < CommonTagsCount, "tag not found");
return idx;
}
template<int Tag>
TagEntity& getTagEntity()
{
return _commonTags[index<Tag>()];
}
std::array<TagEntity, CommonTagsCount> _commonTags; // or else use std::unordered_set, which is not as fast as this approach: absolute O(1) in runtime
};
int main(int argc, char** argv)
{
using MyCommonTags = mpl::vector_c<int,
11,
35,
10914,
10916>;
FixMsg<MyCommonTags> fixMsg;
auto& tagEntity = fixMsg.getTagEntity<11>();
tagEntity.isValid = true;
tagEntity.value = "Get tag entity in O(1)";
cout << tagEntity.value << endl;
I use boost::mpl (and boost::fusion) extensively in my stat_log library. This library allows the user to specify a hierarchy of statistic and logging tags and their associated behaviors, i.e. per-tag statistic types (histogram, counter, etc).
I rely heavily on metaprogramming to do the right thing with the user does:
stat_log::writeStat<IP_PKTS_RCVD>(450);
For example if the user defines the type trait:
template <>
struct stat_tag_to_type<IP_PKTS_RCVD>
{
using type = Accumulator<
stat_log::HistogramCount<
int,
1, //start bin
1500, //stop bin
10 //num_bits
>
>;
};
the "writeStat" call above will proxy (at compile time) to a histogram statistic. The powerful aspect of this design technique is the "writeStat" call site is not at all coupled with the particular statistic chosen.
I also use a wealth of MPL and boost::fusion to actually view the stats. Per your question, see the following files for the highest concentration of boost::mpl:
https://github.com/rjmccabe3701/stat_log/blob/master/include/stat_log/util/stat_log_impl.h
https://github.com/rjmccabe3701/stat_log/blob/master/include/stat_log/util/tag_commander.h
https://github.com/rjmccabe3701/stat_log/blob/master/include/stat_log/stat_log.h
especially the nifty template meta "function" in stat_log_impl.h:
//This template is used in conjunction with an MPL algorithm
// with the same semantics as mpl::find_if.
//BoolFunc is the "condition" metafunction.
//StatTagFunc is a metafunction that transforms the given
// stat_tag into something the algorithm requires.
// For example the "Identity" metafunction would work here.
//StatTagArgs is extra arguments to the BoolFunc
template <template<typename...> class BoolFunc,
template<typename...> class StatTagFunc,
class... StatTagArgs>
struct tag_node_query
{
template<typename TheTagNode>
struct apply
{
using stat_tag = typename TheTagNode::tag;
using type = std::integral_constant
<
bool,
BoolFunc<
typename StatTagFunc<stat_tag>::type,
StatTagArgs...
>::value
>;
};
};
To add to Matthieu's answer, it's also used quite extensively throughout both Boost.Python and Luabind.
Something funny I did:
https://github.com/edubois/static-factorial/blob/master/main.cpp
It uses a tiny part of boost::mpl to statically compute the value of factorial<8>()...
This can help to understand the main idea.