【问题标题】:How to use boost preprocessors to run a sequence of functions?如何使用 boost 预处理器来运行一系列函数?
【发布时间】:2014-06-11 12:12:57
【问题描述】:

例如,我有一系列具有相同两个参数类型的函数 f1、f2 等。我想使用宏

RUN((f1)(f2)(f3), a, b)

使用结果运行函数序列

f1(a, b), f2(a, b), f3(a, b)

我认为 boost 预处理器可以提供帮助。我试过了

#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)

这种技术也适用于调用一系列宏。

【问题讨论】:

  • 你想达到什么目的?这似乎可以通过模板实现。
  • “但失败了” - 如何失败了?
  • 关于您的编辑:呃-呃。不,这是一个完全不同的问题,所以如果你想问这个问题,请单独发布!对于下面的原始问题,您已经有了一个出色的答案。我已回滚您的编辑。
  • @edit:不要这样做,只需输入,这是一次编写的代码。 = 默认存在是有原因的。
  • @user1899020 他们是不同的问题。事实上,完全不同。我知道您可能不会立即意识到这一点,但请相信我们这一点。 之后更改问题是不好的,因为这会使他的答案看起来不适用于您提出的问题。但我认为你已经得到了答案?

标签: c++ boost boost-preprocessor


【解决方案1】:

您不需要在这里使用宏。看到它Live On Coliru

#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++ 中的一等语言公民。

最后,让我们展示一下它适用于可变参数列表:

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>>]

【讨论】:

  • 在预处理器足够的情况下加入phoenixfusion 对我来说似乎有点矫枉过正。
  • @MartinBa 我倾向于将宏视为最后的手段。在这种情况下,您能展示有效的宏解决方案吗?我可能会投票
  • 这个函数其实也是一个宏。
  • @user1899020 哦,太好了 :( 这让这个问题非常具有误导性。
  • @user1899020:你没有“编辑”它;你用一个完全不同的替换它。我回滚了。
猜你喜欢
  • 2011-09-23
  • 2014-10-01
  • 2014-08-10
  • 2015-01-03
  • 2020-12-09
  • 2015-07-12
  • 2020-11-26
  • 1970-01-01
相关资源
最近更新 更多