Compile-Time用于控制算法的仿函数容器?

时间:2010-11-09 10:18:24

标签: c++ generic-programming boost-fusion template-meta-programming

假设我想要一些简单的东西:

我有一个核心算法,它随机选择一个专门的算法(专门编译时)并处理这个算法。这些专业算法通过仿函数实现。

现在的问题是:如何实现一个在编译时构建的容器,其中核心算法可以首先检查这个容器的大小(“我有4个算法 - &gt ;需要随机选择算法0-3“)然后可以在此容器中执行仿函数(”随机选择2 - >处理容器中的第三个仿函数“)。

如何尽可能简单地实现它?我想这是可能的。

是否与好奇的重复出现的模板成语有关联? (wiki link
使用 Boost :: Fusion 有一种简单的方法吗? (official doc

编辑:所有算法都将用于核心算法。使用模式(随机数)是运行时决策(所以我不需要编译时间)。该算法只需要知道仿函数的容器和这个容器的大小,以便安全访问。

3 个答案:

答案 0 :(得分:3)

如果您希望核心算法执行专门的算法,核心算法和专用算法之间应该存在某种契约。

如果将此合约定义为接口,则容器只是一个包含指向这些接口的指针的容器,例如:

class IAlgorithm
   {
   public:
      virtual double operator()(double d) = 0;
   };

typedef std::vector<IAlgorithm *> Algorithms;

调用随机算法然后简单地取矢量的大小,取零和列表大小之间的随机值(0..size-1),取该位置的条目并调用接口。 / p>

或者,您也可以使用新的C ++ 0x std :: function构造,如下所示:

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

采用类似的算法,您应该可以调用这样的算法:

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

这种方法的优点是你也可以使用lambda。

编辑:这是一个使用lambda的示例。它使用Visual Studio 2010编译并按预期工作(我自己测试过):

#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;
}

答案 1 :(得分:0)

我不是专家,但我认为确实是boost :: fusion和/或boost::mpl是你正在寻找的工具。

你的类将把一个mpl容器作为参数,作为算法函数类型的列表,然后在编译时使用它。

答案 2 :(得分:0)

我认为一个有趣的子问题是如何在编译时生成随机数。

也许是这样的事情:)

//compiletime_rand.h

#ifndef COMPILETIME_RAND_GENERATOR_H
#define COMPILETIME_RAND_GENERATOR_H

template <unsigned N, unsigned Seed, unsigned Modulo>
struct rand_c_impl
{
    static const unsigned value_impl = (1664525 * rand_c_impl<N - 1, Seed, Modulo>::value + 1013904223) % (1ull << 32);
    static const unsigned value = value_impl % Modulo;
};

template <unsigned Seed, unsigned Modulo>
struct rand_c_impl<0, Seed, Modulo>
{
    static const unsigned value_impl = Seed;
    static const unsigned value = value_impl;
};

#endif

//next_c_rand.h

#include BOOST_PP_UPDATE_COUNTER()

rand_c_impl<BOOST_PP_COUNTER, 0, MAX_C_RAND>::value

//main.cpp

#include <boost/preprocessor/slot/counter.hpp>
#include "compiletime_rand.h"

#include <iostream>

#define MAX_C_RAND 16

template <unsigned N>
void output_compiletime_value()
{
    std::cout << N << '\n';
}

int main()
{
    output_compiletime_value< 
#include "next_c_rand.h"
    >();
    output_compiletime_value< 
#include "next_c_rand.h"
    >();  
}

输出:15 2