Интересный вопрос. Нормальный это не сработает, потому что не существует способа представления типа во время выполнения с той же семантикой, которая известна из времени компиляции, например, нет виртуальных конструкторов (см. Раздел 8.2 Модерара C++ Design, стр. 200). Но fusion поддерживает 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
- маленький помощник для создания фильтра. Теперь осталось два фрагмента кода слева: мой очень специальный предикат mypred
, который принимает только char
(вам нужно иметь дело с перегрузкой для более общих реализаций) и мой объект функции fun
, который выводит информацию о типе и значение. В основном for_each
вызывается с filter
. Обратите внимание: фильтр предназначен для использования объекта функции по ссылке, чтобы он мог переносить аргументы и результат. В конце это вариация ad hoc visitation. Если вы относитесь к скорости, вы должны знать, что все может быть встроено. В этом конкретном примере сравниваются только символы, для всех остальных типов результат равен false
, и функция не вызывается. Конечно, есть много возможностей для улучшения, но у меня нет времени на это. Там могут быть лучшие способы реализовать это, но это была моя первая программа с boost.fusion :-).
На самом деле мотивация была волшебным переключателем ... http://stackoverflow.com/questions/16691214/is-it-possible-to-map-intenum-to-type Недавно я наткнулся на слияние, и мне было интересно, есть ли слияние возможно, волшебство, которое я искал :) – NoSenseEtAl