興味深い質問です。通常、これは機能しません。たとえば、仮想コンストラクターがないなど、コンパイル時に既知の同じセマンティクスで実行時に型を表す方法がないためです (Moder C++ Design ページ 200、パラグラフ 8.2 を参照)。ただし、フュージョンは、コンパイル時にシーケンスfor_each
を反復処理し、ランタイム関数オブジェクトを呼び出すものをサポートしています。現在、この関数オブジェクトは、ジェネリック述語が true を返す場合、別のジェネリック関数オブジェクトへの呼び出しを転送するジェネリック フィルターにすることができます。
今彼女はコードです:
#include <boost/fusion/container/map.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <string>
#include <iostream>
#include <typeinfo>
using namespace boost::fusion;
template<class Pred,class Fun>
struct filter {
Pred pred_;
Fun& fun_;
filter(Pred p, Fun& f)
: pred_(p)
, fun_(f)
{}
template<class Pair>
void operator()(Pair& pair) const {
if (pred_(pair.second))
fun_(pair);
}
};
template<class Pred,class Fun>
filter<Pred,Fun> make_filter(Pred p, Fun& f) {
return filter<Pred,Fun>(p, f);
}
typedef map
< pair<int, char>
, pair<double, std::string>
> map_type;
struct fun {
template<class First,class Second>
void operator()(pair<First,Second>& t) const {
std::cout
<< typeid(First).name() << std::endl
<< typeid(Second).name() << ":" << t.second << std::endl;
}
};
struct mypred {
template<class T>
bool operator()(T const&) const {
return false;
}
bool operator()(char c) const {
return c=='X';
}
};
int main(int argc, char** argv) {
map_type m(
make_pair<int>('X'),
make_pair<double>("Men")
);
for_each(m, make_filter(mypred(),fun()));
return 0;
}
フィルター クラスには、述語と関数オブジェクトが格納されます。述語がtrueを返す場合、pair.second
あなたの場合'X'
、関数オブジェクトを呼び出します。make_filter
フィルターを作成するための小さなヘルパーです。これで 2 つの部分のコードが残っています: 私の非常に特別な predicatemypred
のみを受け入れます (より一般的な実装では、オーバーロードを処理する必要があります) と、型情報と値を出力char
する関数オブジェクトです。fun
in mainfor_each
は で呼び出されfilter
ます。注意: フィルタは関数オブジェクトを参照で取得するように設計されているため、引数と結果を転送できます。最後に、これはアドホック ビジットのバリエーションです。. 速度が気になる場合は、ほとんどすべてをインライン化できることを知っておく必要があります。この特定の例では、char のみが比較され、他のすべての型については結果が返され、false
関数は呼び出されません。もちろん、改善の余地はたくさんありますが、今はそれをする時間がありません。これを実装するより良い方法があるかもしれませんが、これはboost.fusionを使った私の最初のプログラムでした:-)。