2013-06-30 4 views
2

Я хотел бы иметь значение типа карты, и из того, что я вижу, boost fusion использует карту, в которой используется пара, где type всегда является первым memeber (так это ключ на карте)?Можно ли использовать форсированную карту слияния в обратном направлении, иначе ключ 567, значение типа?

map_type m(
    fusion::make_pair<int>('X') 
    , fusion::make_pair<double>("Men")); 

Возможно ли присвоить значение (например, «X» в примере выше) значение ключа и типа? Если нет, я могу по крайней мере сделать фильтр на основе значения (это медленно, поэтому было бы неплохо узнать, могу ли я сортировать вектор слияния на основе второго параметра и использовать для него binary_search (опять же с пользовательским компаратором, который смотрит на значение, а не на ключ).

ответ

1

Может быть, не в boost::fusion, но трюк, где взять список значений во время выполнения и вызов функтора с типом зависимости от того, соответствует существует. Я называю это волшебным переключателем.

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

Вы не можете возвращает тип, но вместо этого вы можете вызвать переданный в шаблоне functo с типом.

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

+0

На самом деле мотивация была волшебным переключателем ... http://stackoverflow.com/questions/16691214/is-it-possible-to-map-intenum-to-type Недавно я наткнулся на слияние, и мне было интересно, есть ли слияние возможно, волшебство, которое я искал :) – NoSenseEtAl

1

Интересный вопрос. Нормальный это не сработает, потому что не существует способа представления типа во время выполнения с той же семантикой, которая известна из времени компиляции, например, нет виртуальных конструкторов (см. Раздел 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 :-).

 Смежные вопросы

  • Нет связанных вопросов^_^