C++11 Automate creation of integer to enum value map - c++

I need to create a map of int to enum values. (I'm reading integers in a file and need to create an enum from them at runtime.) I can manually create a map as shown in my example below. However this is a trivial example with only a few (i.e., seven) elements of my enum.
My real-world-problem has several hundred elements of my enum class. I don't need to print the names of my real-world enum, but I do need to get the enum value given an integer. I already have the enum class created and want an automatic way to create a map from an integer to the enum value.
I'm looking to automate the creation of the map which I've called WeekMap so I can pass it an integer and get the enum value. Is this even possible? Please tell me it is.
// Compile with:
// clang++ -std=c++11 -stdlib=libc++ enum_test.cpp -o enum_test
//
#include <iostream>
#include <string>
#include <map>
enum class Days {
SUNDAY = 1,
MONDAY = 2,
TUESDAY = 3,
WEDNESDAY = 4,
THURSDAY = 5,
FRIDAY = 6,
SATURDAY = 7
};
std::ostream& operator<< (std::ostream& os, const Days& day){
os << static_cast<std::underlying_type<Days>::type>(day);
return os;
}
std::map<unsigned int, Days> WeekMap{
{1, Days::SUNDAY},
{2, Days::MONDAY},
{3, Days::TUESDAY},
{4, Days::WEDNESDAY},
{5, Days::THURSDAY},
{6, Days::FRIDAY},
{7, Days::SATURDAY},
};
// Return the day of the week
Days WhatDay(unsigned int D){
return WeekMap[D];
}
int main() {
std::cout << "\nLearning how to 'cout' enums." << std::endl;
Days myDay = Days::MONDAY;
std::cout << "\nMonday is day: " << myDay << "\n" << std::endl;
for (int i=1; i<8; i++){
std::cout << "Day number: " << i << " is " << WhatDay(i) << std::endl;
}
return 0;
}

You do not need the map. Your WhatDay function can be written like this:
Days WhatDay (unsigned int D) {
return static_cast<Days>(D);
}
This is basically free (in efficiency terms.) But you might want to make sure your enum's underlying type is indeed an int (or something smaller or larger;) again for efficiency reasons and for reliability reasons:
enum class Days : int {
...
};
What you will lose, however, with this method is error checking. You won't be able to check whether the integer is a valid enumeration value or not; especially if your enum values are not contiguous.
UPDATE 2 (Update 1 is below!)
To somewhat automate creation of this kind of enum, and a whole lot of other code, you can use the following technique:
You first write down the data you are interested in, in a general format:
#define EXPAND_VALUES(action) \
action (1, SUNDAY, "Sunday") \
action (2, MONDAY, "Monday") \
action (3, TUESDAY, "Tuesday") \
action (4, WEDNESDAY, "Wednesday") \
action (5, THURSDAY, "Thursday") \
action (6, FRIDAY, "Friday") \
action (7, SATURDAY, "Saturday")
// Note the lack of a separator after the entries; this is more flexible.
This is all the information I have about each of the entries, in a general form (i.e. passed to an unknown function-like thing called action.
Now, to define the enumeration, we can simply say:
#define DEF_ENUM(i,v,s) v = i,
enum class Days : int { EXPAND_VALUES(DEF_ENUM) };
#undef DEF_ENUM
As further examples, you can define the map you want, and another table that maps enum values to strings like this:
#define DEF_MAP(i,v,s) {i, Days::v},
std::map<int, Days> WeekMap { EXPAND_VALUES(DEF_MAP) };
#undef DEF_MAP
#define DEF_STR_MAP(i,v,s) {Days::v, s},
std::map<Days, std::string> WeekStrMap { EXPAND_VALUES(DEF_STR_MAP) };
#undef DEF_STR_MAP
(This sample code is available on Ideone.)
Note what this technique does for you. Without any redundancy in data definition, you get as many data-structure definitions, array initializations, switch-statement cases, if-else if-else constructs, etc. you want out of that data. And all of this is done at compile time (or before) without any hassles.
This is an extremely powerful technique that might (or might not) be useful to you.
UPDATE 1 (In response to the updated question):
No, it is not possible to create an enum at runtime in C++. You cannot create a new type for the compiler at runtime, when there is no more compiler (if this is really what you're after.)
However, since enums in C++ offer absolutely no runtime facilities, then, at runtime, there is no difference between two enums with the same underlying type. Or in fact, between an enum and an int (if int is the underlying type for that enum.)
Therefore, I propose this: you define an empty enum, and write the WhatDay function exactly as before. And everything will be fine! (Since you don't need bounds checking.)
Specifically, what I'm proposing is this:
enum class Days : int { /*really, really empty!*/ };
Days WhatDay (unsigned int D) {
return static_cast<Days>(D);
}
This works because it seems to me that you do not know your enumeration values at compile time, and the compiler doesn't care one bit for the values of an enum at runtime. No one does!
And if you want error and range checking, I suggest you use an "Interval Tree" (read up on it on Wikipedia.) You populate this tree when you read your enum values from your file at runtime (and this is the only data structure you populate,) and then check each value passed to the WhatDay function against it.

Related

C++ constexpr array lookup: memory overhead? Other gotchas?

I've implemented a constexpr map array lookup based on this SO answer, but it leaves me wondering now what the memory overhead might be like if the map array is very large, and what other gotchas might exist with this technique, particularly if the constexpr function cannot be resolved at compile time.
Here is a contrived code example that hopefully makes my question more clear:
example.h:
enum class MyEnum
{
X0,
X1,
X2,
X3,
X4,
X5
};
struct MyStruct
{
const MyEnum type;
const char* id;
const char* name;
const int size;
};
namespace
{
constexpr MyStruct myMap[] = {
{MyEnum::X0,"X0","Test 0", 0},
{MyEnum::X1,"X1","Test 1", 1},
{MyEnum::X2,"X2","Test 2", 2},
{MyEnum::X3,"X3","Test 3", 3},
{MyEnum::X4,"X4","Test 4", 4},
{MyEnum::X5,"X5","Test 5", 5},
};
constexpr auto mapSize = sizeof myMap/sizeof myMap[0];
}
class invalid_map_exception : public std::exception {};
// Retrieves a struct based on the associated enum
inline constexpr MyStruct getStruct(MyEnum key, int range = mapSize) {
return (range == 0) ? (throw invalid_map_exception()):
(myMap[range - 1].type == key) ? myMap[range - 1]:
getStruct(key, range - 1);
};
example.cpp:
#include <iostream>
#include <vector>
#include "example.h"
int main()
{
std::vector<MyEnum> enumList = {MyEnum::X0, MyEnum::X1, MyEnum::X2, MyEnum::X3, MyEnum::X4, MyEnum::X5};
int idx;
std::cout << "Enter a number between 0 and 5:" << std::endl;
std::cin >> idx;
MyStruct test = getStruct(enumList[idx]);
std::cout << "choice name: " << test.name << std::endl;
return 0;
}
Output:
Enter a number between 0 and 5:
1
choice name: Test 1
Compiled with g++ with -std=c++14.
In the above example, although getStruct is a constexpr function, it cannot be fully resolved until runtime since the value of idx is not known until then. May that change the memory overhead when compiled with optimization flags, or would the full contents of myMap be included in the binary regardless? Does it depend on the compiler and optimization setting used?
Also, what if the header file is included in multiple translation units? Would myMap be duplicated in each one?
I imagine this could be important if the map array becomes enormous and/or the code is going to be used in more resource constrained environments such as embedded devices.
Are there any other potential gotchas with this approach?
If you call a constexpr function with a non-constant expression, it will call the function at run time.
If you call getStruct with a constant expression, the compiler can just call the function at compile time. Then, the getStruct function will be "unused" at runtime, and the compiler will probably optimise it out. At this point, myMap will also be unused, and be optimised out.
In terms of runtime size, it would actually probably be smaller than an std::unordered_map or std::map; It literally stores the minimum information necessary. But it's lookup time would be a lot slower, as it has to compare all the elements individually in O(N) time, so it doesn't actually do what a map does (reduce lookup time).
If you want to make it more likely that it is optimised out, I would ensure that it is only used in constant-expression situations:
template<MyEnum key>
struct getStruct
{
static constexpr const MyStruct value = _getStruct(key);
}
Here's some compiler output that shows that the map is optimised out entirely
And about including it in multiple translation units, it would be duplicated in every one since you use an anonymous namespace to define it. If it was optimised out in all of them, there would be no overhead, but it would still be duplicated for every translation unit that you do a runtime lookup in.

defining an unusual 2-D array in C++

I want to reference the 1st Dimension of a 2 Dimensional array using an enum. However, the configurations that each enum value represents sometimes overlap (not in any patterned way), meaning the data in the array will sometimes be the same. I therefore would like to have some elements point to the same array of data, as in the diagram below.
Is there any way of doing this at declaration-time in C++?
Yes, you can build an array like that using an array of pointers; you will be able to reference elements in that array as if it were a regular 2D array. Here is an example:
enum MyEnum {
enumFirst = 0
, enumSecond = 1
, enumSecondShared = 2
, enumThird = 3
};
static int enumFirstData[] = {1, 2, 3};
static int enumSecondData[] = {4, 3, 2};
static int enumThirdData[] = {9, 7, 8};
int *enumData[] = {
enumFirstData
, enumSecondData
, enumSecondData // <== Shared
, enumSecondData
};
Now you can reference elements of this array like this:
for (int i = 0 ; i != 3 ; i++) {
cout << enumData[enumSecondShared][i] << endl;
}
Since you are using C++, using std::vector or std::array is a preferred way of making collections. You can use the same trick as above to establish shared collection elements.
you can define your own container type and use switch/case to map from the enums to the references. that way, you map those enums at declaration time, can use arbitrary enum values, and are more type safe than indexing an array of pointers.
it would look somehow like this (not tested), which specializes the std::map class:
template<class V>
class map<myenum,V>{
V r1,r2,r3;
public:
inline map(){}
inline r1& operator[](myenum e){
switch(e)
{
case E1: return r1;
case E2:
case E3: return r2;
case E4:
case E5: return r3;
}
}
}
map<myenum,vector<int>> example;
(sorry for not writing high-quality std-template style definitions, i'm not that used to program in c++ anymore.)
All you need is just std::map<your_enum_t, data_t*>
You should feel mapping according to your needs

Better design for using function pointers with varying arguments

I have an optimisation algorithm which finds the best partition of a graph.
There are many measures for the quality of a partition (the variable being optimised), so I thought it would be a good idea to use function pointers to these quality functions, and pass that into my optimisation algorithm function.
This works fine, but the problem is different quality functions take some different arguments.
For example one quality function is find_linearised_stability and it requires a markov_time parameter:
float find_linearised_stability(cliques::Graph<T> &my_graph, cliques::Partition &my_partition,
std::vector<float> &markov_times, std::vector<float> &stabilities)
and is used in the optimisation function :
cliques::find_optimal_partition_louvain(my_new_graph, markov_times, &cliques::find_linearised_stability);
however another quality function find_modularityrequires no markov_time parameter. Of course I could just include it as an argument and not use it in the function but that seems like bad practice, and would get unwieldy once I start adding a lot of different quality functions.
What is a better design for this kind of situation?
Use function objects. One of those function objects can have a markov_time member that is passed in to the constructor:
struct find_linearised_stability {
std::vector<float> & markov_times_;
find_linearised_stability(std::vector<float> & markov_times)
:markov_times_(markov_times)
{}
float operator () (cliques::Graph<T> &my_graph, cliques::Partition &my_partition,
std::vector<float> &stabilities)
{
// use markov_times_ in here, we didn't need to pass it since it's a member
}
};
(you may need to make adjustments to constness/referenceness to suit your needs)
Then you can call your function like this:
cliques::find_optimal_partition_louvain(my_new_graph, cliques::find_linearised_stability(markov_times));
"what type for the function object do I use when declaring the ... function?"
Make it a function template that takes the function object type as a template parameter, thusly:
template<typename PR>
whatever find_optimal_partition_louvain(my_new_graph, PR & pr)
{
...
pr(my_new_graph, partition, stabilities);
...
}
Your only option is boost::bind or something like it stored in a boost::function or something like it.
If profiling shows that to be too slow then you'll be stuck with the "poor practice" version because any alternative is going to run afoul of UB and/or end up being just as 'slow' as the more reasonable alternative.
parameter is not known before: add argument to every function (reference/pointer) that contains all info, every function uses whatever it needs
parameter is known before: use boost::bind, e.g.:
sample source code:
#include <iostream>
#include <cstddef>
#include <algorithm>
#include <boost/bind.hpp>
using namespace std;
void output(int a, int b)
{
cout << a << ", " << b << '\n';
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5 };
for_each(arr, arr + 5, bind(output, 5, _1));
return 0;
}
Outputs:
5, 1
5, 2
5, 3
5, 4
5, 5

How do I increment an enum in VS C++ 6.0?

I copy and pasted some code that increments an enum:
myenum++;
This code worked fine as it was compiled in VS.NET C++ 2003
I am now developing in VS 6.0 and get the error:
error C2676: binary '++' : 'enum
ID' does not define this
operator or a conversion to a type
acceptable to the predefined operator
How can I get this to behave the same in 6.0?
I see nothing wrong with defining operator++ on a well understood enum. Isn't that the purpose of operator overloading? If the context made no sense (e.g. an enum with holes in it), then of course it doesn't make sense. Defining operator* for a class called Complex that implement complex numbers is not just valid but a great application of mathematical operator overloading in C++!
If the developer defines an enum where operator++ makes obvious and intuitive sense to the clients of that enum, then that's a good application of that operator overload.
enum DayOfWeek {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday};
inline DayOfWeek operator++(DayOfWeek &eDOW, int)
{
const DayOfWeek ePrev = eDOW;
const int i = static_cast<int>(eDOW);
eDOW = static_cast<DayOfWeek>((i + 1) % 7);
return ePrev;
}
an enum may be intergral but it doesn't mean it covers a continuous range.
This
enum {
A,
B,
C,
}
May Will default to
enum {
A = 0,
B = A + 1,
C = B + 1,
}
and so you could get away with
int a = A;
a++;
However if you have
enum {
A = 2,
B = 4,
C = 8,
}
now +1 ain't gonna work.
Now, if you also had things like
enum {
FIRST,
A = FIRST,
B,
C,
LAST = C
}
then when iterating the enum would you do A and C twice?
What is the purpose of iterating the enum? do you wish to do 'for all' or for some subset, is there actually an order to the enum?
I'd throw them all in a container and iterate that instead
unordered - use a set
ordered - a vector or list
Please try to convert to int, add one (+1) and convert back to the enum.
myenum=(myenum_type)((int)myenum+1);
It's ugly but it works.

What is metaprogramming?

With reference to this question, could anybody please explain and post example code of metaprogramming? I googled the term up, but I found no examples to convince me that it can be of any practical use.
On the same note, is Qt's Meta Object System a form of metaprogramming?
jrh
Most of the examples so far have operated on values (computing digits of pi, the factorial of N or similar), and those are pretty much textbook examples, but they're not generally very useful. It's just hard to imagine a situation where you really need the compiler to comput the 17th digit of pi. Either you hardcode it yourself, or you compute it at runtime.
An example that might be more relevant to the real world could be this:
Let's say we have an array class where the size is a template parameter(so this would declare an array of 10 integers: array<int, 10>)
Now we might want to concatenate two arrays, and we can use a bit of metaprogramming to compute the resulting array size.
template <typename T, int lhs_size, int rhs_size>
array<T, lhs_size + rhs_size> concat(const array<T, lhs_size>& lhs, const array<T, rhs_size>& rhs){
array<T, lhs_size + rhs_size> result;
// copy values from lhs and rhs to result
return result;
}
A very simple example, but at least the types have some kind of real-world relevance. This function generates an array of the correct size, it does so at compile-time, and with full type safety. And it is computing something that we couldn't easily have done either by hardcoding the values (we might want to concatenate a lot of arrays with different sizes), or at runtime (because then we'd lose the type information)
More commonly, though, you tend to use metaprogramming for types, rather than values.
A good example might be found in the standard library. Each container type defines its own iterator type, but plain old pointers can also be used as iterators.
Technically an iterator is required to expose a number of typedef members, such as value_type, and pointers obviously don't do that. So we use a bit of metaprogramming to say "oh, but if the iterator type turns out to be a pointer, its value_type should use this definition instead."
There are two things to note about this. The first is that we're manipulating types, not values We're not saying "the factorial of N is so and so", but rather, "the value_type of a type T is defined as..."
The second thing is that it is used to facilitate generic programming. (Iterators wouldn't be a very generic concept if it didn't work for the simplest of all examples, a pointer into an array. So we use a bit of metaprogramming to fill in the details required for a pointer to be considered a valid iterator).
This is a fairly common use case for metaprogramming. Sure, you can use it for a wide range of other purposes (Expression templates are another commonly used example, intended to optimize expensive calculations, and Boost.Spirit is an example of going completely overboard and allowing you to define your own parser at compile-time), but probably the most common use is to smooth over these little bumps and corner cases that would otherwise require special handling and make generic programming impossible.
The concept comes entirely from the name Meta- means to abstract from the thing it is prefixed on.
In more 'conversational style' to do something with the thing rather than the thing itself.
In this regard metaprogramming is essentially writing code, which writes (or causes to be written) more code.
The C++ template system is meta programming since it doesn't simply do textual substitution (as the c preprocessor does) but has a (complex and inefficient) means of interacting with the code structure it parses to output code that is far more complex. In this regard the template preprocessing in C++ is Turing complete. This is not a requirement to say that something is metaprogramming but is almost certainly sufficient to be counted as such.
Code generation tools which are parametrizable may be considered metaprogramming if their template logic is sufficiently complex.
The closer a system gets to working with the abstract syntax tree that represents the language (as opposed to the textual form we represent it in) the more likely it is to be considered metaprogramming.
From looking at the QT MetaObjects code I would not (from a cursory inspection) call it meta programming in the sense usually reserved for things like the C++ template system or Lisp macros. It appears to simply be a form of code generation which injects some functionality into existing classes at the compile stage (it can be viewed as a precursor to the sort of Aspect Oriented Programming style currently in vogue or the prototype based object systems in languages like JavaScripts
As example of the sort of extreme lengths you can take this in C++ there is Boost MPL whose tutorial shows you how to get:
Dimensioned types (Units of Measure)
quantity<float,length> l( 1.0f );
quantity<float,mass> m( 2.0f );
m = l; // compile-time type error
Higher Order Metafunctions
twice(f, x) := f(f(x))
template <class F, class X>
struct twice
: apply1<F, typename apply1<F,X>::type>
{};
struct add_pointer_f
{
template <class T>
struct apply : boost::add_pointer<T> {};
};
Now we can use twice with add_pointer_f to build pointers-to-pointers:
BOOST_STATIC_ASSERT((
boost::is_same<
twice<add_pointer_f, int>::type
, int**
>::value
));
Although it's large (2000loc) I made a reflexive class system within c++ that is compiler independant and includes object marshalling and metadata but has no storage overhead or access time penalties. It's hardcore metaprogramming, and being used in a very big online game for mapping game objects for network transmission and database-mapping (ORM).
Anyways it takes a while to compile, about 5 minutes, but has the benefit of being as fast as hand tuned code for each object. So it saves lots of money by reducing significant CPU time on our servers (CPU usage is 5% of what it used to be).
Here's a common example:
template <int N>
struct fact {
enum { value = N * fact<N-1>::value };
};
template <>
struct fact<1> {
enum { value = 1 };
};
std::cout << "5! = " << fact<5>::value << std::endl;
You're basically using templates to calculate a factorial.
A more practical example I saw recently was an object model based on DB tables that used template classes to model foreign key relationships in the underlying tables.
Another example: in this case the metaprogramming tecnique is used to get an arbitrary-precision value of PI at compile-time using the Gauss-Legendre algorithm.
Why should I use something like that in real world? For example to avoid repeating computations, to obtain smaller executables, to tune up code for maximizing performance on a specific architecture, ...
Personally I love metaprogramming because I hate repeating stuff and because I can tune up constants exploiting architecture limits.
I hope you like that.
Just my 2 cents.
/**
* FILE : MetaPI.cpp
* COMPILE : g++ -Wall -Winline -pedantic -O1 MetaPI.cpp -o MetaPI
* CHECK : g++ -Wall -Winline -pedantic -O1 -S -c MetaPI.cpp [read file MetaPI.s]
* PURPOSE : simple example template metaprogramming to compute the
* value of PI using [1,2].
*
* TESTED ON:
* - Windows XP, x86 32-bit, G++ 4.3.3
*
* REFERENCES:
* [1]: http://en.wikipedia.org/wiki/Gauss%E2%80%93Legendre_algorithm
* [2]: http://www.geocities.com/hjsmithh/Pi/Gauss_L.html
* [3]: http://ubiety.uwaterloo.ca/~tveldhui/papers/Template-Metaprograms/meta-art.html
*
* NOTE: to make assembly code more human-readable, we'll avoid using
* C++ standard includes/libraries. Instead we'll use C's ones.
*/
#include <cmath>
#include <cstdio>
template <int maxIterations>
inline static double compute(double &a, double &b, double &t, double &p)
{
double y = a;
a = (a + b) / 2;
b = sqrt(b * y);
t = t - p * ((y - a) * (y - a));
p = 2 * p;
return compute<maxIterations - 1>(a, b, t, p);
}
// template specialization: used to stop the template instantiation
// recursion and to return the final value (pi) computed by Gauss-Legendre algorithm
template <>
inline double compute<0>(double &a, double &b, double &t, double &p)
{
return ((a + b) * (a + b)) / (4 * t);
}
template <int maxIterations>
inline static double compute()
{
double a = 1;
double b = (double)1 / sqrt(2.0);
double t = (double)1 / 4;
double p = 1;
return compute<maxIterations>(a, b, t, p); // call the overloaded function
}
int main(int argc, char **argv)
{
printf("\nTEMPLATE METAPROGRAMMING EXAMPLE:\n");
printf("Compile-time PI computation based on\n");
printf("Gauss-Legendre algorithm (C++)\n\n");
printf("Pi=%.16f\n\n", compute<5>());
return 0;
}
The following example is lifted from the excellent book C++ Templates - The complete guide.
#include <iostream>
using namespace std;
template <int N> struct Pow3 {
enum { pow = 3 * Pow3<N-1>::pow };
}
template <> struct Pow3<0> {
enum { pow = 1 };
}
int main() {
cout << "3 to the 7 is " << Pow<7>::pow << "\n";
}
The point of this code is that the recursive calculation of the 7th power of 3 takes place at compile time rather than run time. It is thus extremely efficient in terms of runtime performance, at the expense of slower compilation.
Is this useful? In this example, probably not. But there are problems where performing calculations at compile time can be an advantage.
It's hard to say what C++ meta-programming is. More and more I feel it is much like introducing 'types' as variables, in the way functional programming has it. It renders declarative programming possible in C++.
It's way easier to show examples.
One of my favorites is a 'trick' (or pattern:) ) to flatte multiply nested switch/case blocks:
#include <iostream>
using namespace std;
enum CCountry { Belgium, Japan };
enum CEra { ancient, medieval, future };
// nested switch
void historic( CCountry country, CEra era ) {
switch( country ) {
case( Belgium ):
switch( era ) {
case( ancient ): cout << "Ambiorix"; break;
case( medieval ): cout << "Keizer Karel"; break;
}
break;
case( Japan ):
switch( era ) {
case( future ): cout << "another Ruby?"; break;
case( medieval ): cout << "Musashi Mijamoto"; break;
}
break;
}
}
// the flattened, metaprogramming way
// define the conversion from 'runtime arguments' to compile-time arguments (if needed...)
// or use just as is.
template< CCountry country, CEra era > void thistoric();
template<> void thistoric<Belgium, ancient> () { cout << "Ambiorix"; }
template<> void thistoric<Belgium, medieval>() { cout << "Keizer Karel"; }
template<> void thistoric<Belgium, future >() { cout << "Beer, lots of it"; }
template<> void thistoric<Japan, ancient> () { cout << "wikipedia"; }
template<> void thistoric<Japan, medieval>() { cout << "Musashi"; }
template<> void thistoric<Japan, future >() { cout << "another Ruby?"; }
// optional: conversion from runtime to compile-time
//
template< CCountry country > struct SelectCountry {
static void select( CEra era ) {
switch (era) {
case( medieval ): thistoric<country, medieval>(); break;
case( ancient ): thistoric<country, ancient >(); break;
case( future ): thistoric<country, future >(); break;
}
}
};
void Thistoric ( CCountry country, CEra era ) {
switch( country ) {
case( Belgium ): SelectCountry<Belgium>::select( era ); break;
case( Japan ): SelectCountry<Japan >::select( era ); break;
}
}
int main() {
historic( Belgium, medieval ); // plain, nested switch
thistoric<Belgium,medieval>(); // direct compile time switch
Thistoric( Belgium, medieval );// flattened nested switch
return 0;
}
The only time I needed to use Boost.MPL in my day job was when I needed to convert boost::variant to and from QVariant.
Since boost::variant has an O(1) visitation mechanism, the boost::variant to QVariant direction is near-trivial.
However, QVariant doesn't have a visitation mechanism, so in order to convert it into a boost::variant, you need to iterate over the mpl::list of types that the specific boost::variant instantiation can hold, and for each type ask the QVariant whether it contains that type, and if so, extract the value and return it in a boost::variant. It's quite fun, you should try it :)
QtMetaObject basically implements reflection (Reflection) and IS one of the major forms of metaprogramming, quite powerful actually. It is similar to Java's reflection and it's also commonly used in dynamic languages (Python, Ruby, PHP...). It's more readable than templates, but both have their pros and cons.
This is a simple "value computation" along the lines of Factorial. However, it's one you are much more likely to actually use in your code.
The macro CT_NEXTPOWEROFTWO2(VAL) uses template metaprogramming to compute the next power of two greater than or equal to a value for values known at compile time.
template<long long int POW2VAL> class NextPow2Helper
{
enum { c_ValueMinusOneBit = (POW2VAL&(POW2VAL-1)) };
public:
enum {
c_TopBit = (c_ValueMinusOneBit) ?
NextPow2Helper<c_ValueMinusOneBit>::c_TopBit : POW2VAL,
c_Pow2ThatIsGreaterOrEqual = (c_ValueMinusOneBit) ?
(c_TopBit<<1) : c_TopBit
};
};
template<> class NextPow2Helper<1>
{ public: enum { c_TopBit = 1, c_Pow2ThatIsGreaterOrEqual = 1 }; };
template<> class NextPow2Helper<0>
{ public: enum { c_TopBit = 0, c_Pow2ThatIsGreaterOrEqual = 0 }; };
// This only works for values known at Compile Time (CT)
#define CT_NEXTPOWEROFTWO2(VAL) NextPow2Helper<VAL>::c_Pow2ThatIsGreaterOrEqual