2

次のような単純なものが必要だとします。

特殊なアルゴリズム (コンパイル時に特殊化された) の 1 つをランダムに選択し、このアルゴリズムを処理するコア アルゴリズムがあります。これらの特殊なアルゴリズムは、ファンクターを通じて実装されます。

問題は次のとおりです。コンパイル時にビルドされるコンテナーを実装する方法です。コアアルゴリズムは最初にこのコンテナーのサイズを確認できます (「4 つのアルゴリズムを取得しました -> アルゴリズム 0-3 をランダムに選択する必要があります」)そして、このコンテナーでファンクターを実行できます (「ランダムに選択された 2 -> コンテナー内の 3 番目のファンクターを処理する」)。

できるだけ簡単に実装するにはどうすればよいでしょうか。可能だと思います。

奇妙に繰り返されるテンプレートイディオムとの関連はありますか? (ウィキ リンク) Boost::Fusion
を使用する簡単な方法はありますか? (公式ドキュメント)

編集:すべてのアルゴリズムはコアアルゴリズムで使用されます。使用パターン (乱数) は実行時の決定です (したがって、コンパイル時のランドは必要ありません)。アルゴリズムは、安全にアクセスするために、ファンクターのコンテナーとこのコンテナーのサイズを認識している必要があります。

4

3 に答える 3

3

コア アルゴリズムで特殊なアルゴリズムを実行する場合は、コア アルゴリズムと特殊なアルゴリズムの間に何らかの契約が必要です。

このコントラクトをインターフェイスとして定義すると、コンテナーは単にこれらのインターフェイスへのポインターを含むコンテナーになります。たとえば、次のようになります。

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;
}
于 2010-11-09T10:28:37.563 に答える
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

于 2010-11-09T11:40:56.920 に答える
0

私は専門家ではありませんが、boost::fusion やboost::mplはあなたが探しているツールだと思います。

あなたのクラスは、アルゴリズムファンクタータイプのリストである mpl コンテナーをパラメーターとして取り、コンパイル時にそれを操作します。

于 2010-11-09T10:28:08.517 に答える