Например, у меня есть последовательность функций f1, f2 и так далее с одним и тем же типом аргумента. Я хочу использовать макрос
RUN((f1)(f2)(f3), a, b)
запустить последовательность функций с результатами
f1(a, b), f2(a, b), f3(a, b)
Я думаю, что препроцессоры повышения могут помочь. Я старался
#define RUN_DETAIL(pR, pData, pF) pF(a, b);
#define RUN(pFs, a, b) BOOST_PP_SEQ_FOR_EACH(RUN_DETAIL, BOOST_PP_EMPTY, pFs)
Но не удалось. Как это сделать?
Нашел ответ как ниже
#define RUN_DETAIL(pR, pData, pF) pF pData;
#define RUN(pFs, ...) BOOST_PP_SEQ_FOR_EACH(RUN_DETAIL, (__VA_ARGS__), pFs)
Этот метод работает также для вызова последовательности макросов.
Вам не нужно использовать макросы здесь. Видеть это Жить на Колиру:
#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/algorithm.hpp>
#include <boost/phoenix.hpp>
template <typename... F>
struct sequence_application
{
explicit sequence_application(F... fs) : fs(fs...) { }
template <typename... Args>
void operator()(Args const&... args) const {
namespace phx = boost::phoenix;
using namespace phx::arg_names;
boost::fusion::for_each(fs, phx::bind(arg1, phx::cref(args)...));
}
private:
std::tuple<F...> fs;
};
template <typename... F>
sequence_application<F...> apply_all(F&&... fs) {
return sequence_application<F...>(std::forward<F>(fs)...);
}
Давайте продемонстрируем это:
#include <iostream>
#include <string>
void foo(const char* v) { std::cout << __FUNCTION__ << ": " << v << "\n"; }
void bar(std::string v) { std::cout << __FUNCTION__ << ": " << v << "\n"; }
struct poly_functor {
template <typename... T>
void operator()(T&...) const { std::cout << __PRETTY_FUNCTION__ << "\n"; }
};
Вы можете, конечно, сделать прямой вызов, как в вопросе:
poly_functor pf;
apply_all(&foo, &bar, pf)("fixed invocation is boring");
Но это действительно довольно скучно. Как насчет того, мы держим составной функтор и передаем Это в другой алгоритм?
auto combined = apply_all(&foo, &bar, pf);
boost::for_each(
std::vector<const char*> {"hello", "world", "from", "various"},
combined);
Теперь попробуйте это с вашим макро подходом. Макросы не граждане первого класса в C ++.
Наконец, давайте продемонстрируем, что он работает со списками аргументов variadics:
struct /*anonymous*/ { int x, y; } point;
// the variadic case
apply_all(pf)("bye", 3.14, point);
Полные демонстрационные распечатки:
foo: fixed invocation is boring
bar: fixed invocation is boring
void poly_functor::operator()(T &...) const [T = <char const[27]>]
foo: hello
bar: hello
void poly_functor::operator()(T &...) const [T = <const char *const>]
foo: world
bar: world
void poly_functor::operator()(T &...) const [T = <const char *const>]
foo: from
bar: from
void poly_functor::operator()(T &...) const [T = <const char *const>]
foo: various
bar: various
void poly_functor::operator()(T &...) const [T = <const char *const>]
void poly_functor::operator()(T &...) const [T = <char const[4], const double, const <anonymous struct at test.cpp:54:5>>]