Search code examples
c++generic-programmingboost-fusiontemplate-meta-programming

Compile-Time container of functors for controlling an algorithm?


Suppose i want something simple like the following:

I have an core-algorithm, which randomly selects one of the specialized algorithms (specialized at compile-time) and process this algorithm. These specialized algorithms are implemented trough functors.

The question is now: how to implement a container, which is build at compile-time, where the core-algorithm can first check the size of this container ("i got 4 algorithms -> need to randomly select algorithm 0-3") and can then execute the functor in this container ("randomly chosen 2 -> process the third functor in container").

How would one implement it as simple as possible? I suppose it is possible.

Is there any connection to the curiously recurring template idiom? (wiki link)
Is there a simple way with the use of Boost::Fusion? (official doc)

Edit: All the algorithms will be used in the core-algorithm. The use pattern (random-numbers) is a runtime-decision (so i don't need compile-time-rands). The algorithm just has to know the container of functors and the size of this container for safe access.


Solution

  • If you want your core-algorithm to execute a specialized algorithm, there should be some kind of contract between the core-algorithm and the specialized algorithm.

    If you define this contract as an interface, your container is simply a container containing pointers to these interfaces, e.g.:

    class IAlgorithm
       {
       public:
          virtual double operator()(double d) = 0;
       };
    
    typedef std::vector<IAlgorithm *> Algorithms;
    

    Calling a random algorithm is then simply taking the size of the vector, taking a random value between zero and the size of the list (0..size-1), taking the entry at that position and calling the interface.

    Alternatively, you can also use the new C++0x std::function construction, like this:

    #include <functional>
    typedef std::function<double(double)> Algorithm;
    typedef std::vector<Algorithm> Algorithms;
    

    Taking an algorithm is similar, you should be able to call an algorithm like this:

    Algorithms myAlgorithms;
    ...
    double myresult = myAlgorithms[2](mydouble);
    

    This approach has the advantage that you can also use lambda's.

    EDIT: This is an example that uses lambda's. It compiles and works as expected with Visual Studio 2010 (just tested this myself):

    #include <iostream>
    #include <vector>
    #include <functional> 
    typedef std::function<double(double)> Algorithm; 
    typedef std::vector<Algorithm> Algorithms; 
    
    int main()
    {
    Algorithms algorithms;
    algorithms.push_back([](double d)->double{return d+d;});
    algorithms.push_back([](double d)->double{return d*d;});
    
    std::cout << algorithms[0](5) << std::endl;
    std::cout << algorithms[1](5) << std::endl;
    }