Контейнер времени компиляции функторов для управления алгоритмом? - PullRequest
2 голосов
/ 09 ноября 2010

Предположим, я хочу что-то простое, например:

У меня есть основной алгоритм, который случайным образом выбирает один из специализированных алгоритмов (специализированный во время компиляции) и обрабатывает этот алгоритм.Эти специализированные алгоритмы реализованы через функторы .

Вопрос теперь : как реализовать контейнер, который создается во время компиляции, где основной алгоритм может сначала проверить размер этого контейнера («у меня есть 4 алгоритма»-> нужно случайным образом выбрать алгоритм 0-3 ") и затем можно выполнить функтор в этом контейнере (" случайно выбранный 2 -> обработать третий функтор в контейнере ").

Как реализовать его так же простокак можно?Я предполагаю, что это возможно.

Есть ли какая-либо связь с странно повторяющейся идиомой шаблона ?( вики-ссылка )
Есть ли простой способ с использованием Boost :: Fusion ?( официальный документ )

Редактировать: Все алгоритмы будут использоваться в core-алгоритме.Шаблон использования (случайные числа) является решением времени выполнения (поэтому мне не нужны ранды времени компиляции).Алгоритм просто должен знать контейнер функторов и размер этого контейнера для безопасного доступа.

Ответы [ 3 ]

3 голосов
/ 09 ноября 2010

Если вы хотите, чтобы ваш основной алгоритм выполнял специализированный алгоритм, между основным алгоритмом и специализированным алгоритмом должен быть какой-то контракт.

Если вы определяете этот контракт как интерфейс, ваш контейнерэто просто контейнер, содержащий указатели на эти интерфейсы, например:

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

typedef std::vector<IAlgorithm *> Algorithms;

Вызов случайного алгоритма - это просто получение размера вектора, принимая случайное значение от нуля до размера списка (0..size-1), принимая запись в этой позиции и вызывая интерфейс.

В качестве альтернативы вы также можете использовать новую конструкцию C ++ 0x std :: function, например:

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

Взяв алгоритм аналогично, вы должны иметь возможность вызывать алгоритм, подобный следующему:

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

Этот подход имеет то преимущество, что вы также можете использовать лямбда-выражения.

РЕДАКТИРОВАТЬ: Это пример, который использует лямбда.Он компилируется и работает, как и ожидалось, с 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;
}
0 голосов
/ 09 ноября 2010

Я думаю, что интересной подзадачей является то, как генерировать случайные числа во время компиляции.

Возможно, что-то вроде этого:)

//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

0 голосов
/ 09 ноября 2010

Я не специалист, но я думаю, что действительно boost :: fusion и / или boost :: mpl - это инструменты, которые вы ищете.

Ваш класс займетконтейнер mpl в качестве параметра, являющийся списком типов функторов алгоритмов, который затем будет работать с ним во время компиляции.

...