Передача / связывание аргументов при использовании boost :: fusion :: for_each - PullRequest
3 голосов
/ 29 июля 2011

Я хотел бы вызвать функцию для всех элементов boost :: fusion :: vector. Элементы имеют следующие типы:

class A {
    ...
    void print_with_prefix(const char *prefix) {
        std::cout << prefix << *this;
    }
};

Можно вызывать эту функцию для каждого элемента следующим образом:

// Call print_with_prefix() on a boost::fusion sequence:

struct CallPrintWithPrefix {
    const char *prefix_;
    CallPrintWithPrefix(const char *prefix) : prefix_(prefix) {}
    template <class T> void operator()(T &element) const {
        element.print_with_prefix(prefix);
    }
}

template <class BoostFusionVector>
void print_all(BoostFusionVector &v, const char *prefix) {
    boost::fusion::for_each(v, CallPrintWithPrefix(prefix));
}

Однако, эта реализация print_all(), включающая вспомогательный класс, довольно уродлива и кажется слишком сложной! Предполагая, что C ++ 0x разрешен, как правильно его реализовать?

1 Ответ

3 голосов
/ 29 июля 2011

То, что вы сделали, это правильный путь.C ++ 0x не может сильно помочь в этом отношении, потому что, например, лямбда-выражения не являются полиморфными, поэтому в конце дня вам придется где-то написать шаблон (который, к сожалению, должен находиться в области пространства имен, даже с C ++0x), как вы это сделали с operator().

Некоторые библиотеки, такие как Boost.Phoenix, позволяют создавать полиморфные функторы на лету.Например, ref(std::cout) << arg1 создает объект, способный передавать любые аргументы std::cout.Это не поможет в вашем случае, так как вы вызываете функцию-член.

Это уже второй раз, когда я упоминаю об этом сегодня, но у меня есть средство make_overload, которое позволяет мне создавать перегруженныефунктор на лету.В вашем случае это может помочь, если набор типов элементов невелик и вряд ли изменится.Например, если предположить, что есть только два таких типа A и B:

auto overload = make_overload(
    [prefix](A& a)
    { a.print_with_prefix(prefix); }
    , [prefix](B& c)
    { b.print_with_prefix(prefix); } );
boost::fusion::for_each(v, overload);
...