boost function_input_iterator范围的快捷语法

时间:2016-06-03 07:03:06

标签: c++ boost

我想知道这种代码是否有快捷语法:

DateTime stdt

两个注释:

  • 我无法使用#include <boost/iterator/function_input_iterator.hpp> #include <boost/range.hpp> int main() { std::function<int (int)> f = [](int i) -> int { // some logic, return int }; auto r = boost::make_iterator_range(boost::make_function_input_iterator(f, 0), boost::make_function_input_iterator(f, 10)); return 0; } 导致:

auto f = [](int i) ->int {...};

使用std :: function会因某种原因修复它。

  • 此外,我无法将error: no type named 'result_type' in 'struct main()::<lambda(int)>'作为临时内联即f传递,因为该函数通过引用获取f。

理想情况下,我希望能够做到:

boost::make_function_input_iterator([](int i) ->int {...}, ...

2 个答案:

答案 0 :(得分:3)

您可以使用添加typedef的简单包装器:

template <typename F>
struct ref_wrap : std::reference_wrapper<F> {
    typedef decltype(std::declval<F>()() result_type;
    ref_wrap(F& f) : std::reference_wrapper<F>(f) {}
};
  

PS。 我使用引用包装器来满足function_input_iterator的要求,这已经要求函数成为左值引用。实际上,你可以把它留下来,因为我们返回函数包装器以及范围,见下文

接下来,有一个帮助器返回该包装器的元组以及在其上构建的迭代器范围:

template <typename F>
struct input_function_range_wrapper {
    struct ref_wrap : std::reference_wrapper<F> {
        typedef decltype(std::declval<F>()()) result_type;
        ref_wrap(F& f) : std::reference_wrapper<F>(f) {}
    } wrap;

    using It = boost::function_input_iterator<ref_wrap, int>;
    boost::iterator_range<It> range;

    template <typename V>
    input_function_range_wrapper(F& f, V a, V b) : wrap(f), range(It(wrap, a), It(wrap, b))
    { }
};

为了方便使用它,我们将其移动到详细命名空间并添加工厂函数:

template <typename F, typename V = int>
auto make_input_function_range(F& f, V a, V b) {
    return detail::input_function_range_wrapper<F>(f, a, b);
}

现在要真正做到最好,我们添加了启用ADL的beginend调用以及PRONTO,我们可以使用c ++的ranged-for:

int main() {
    auto f = [i=1]() mutable { return i*=2; };

    for (auto v : make_input_function_range(f, 0, 10)) {
        std::cout << v << " ";
    }
}

打印

2 4 8 16 32 64 128 256 512 1024 

完全演示

<强> Live On Coliru

#include <boost/iterator/function_input_iterator.hpp>
#include <boost/range.hpp>

namespace detail {

    template <typename F>
    struct input_function_range_wrapper {
        struct ref_wrap : std::reference_wrapper<F> {
            typedef decltype(std::declval<F>()(/*std::declval<V>()*/)) result_type;
            ref_wrap(F& f) : std::reference_wrapper<F>(f) {}
        } wrap;

        using It = boost::function_input_iterator<ref_wrap, int>;
        boost::iterator_range<It> range;

        template <typename V>
        input_function_range_wrapper(F& f, V a, V b) : wrap(f), range(It(wrap, a), It(wrap, b))
        { }
    };

    template <typename... Ts>
        auto begin(input_function_range_wrapper<Ts...>& r)       { return r.range.begin(); }
    template <typename ... Ts>
        auto begin(input_function_range_wrapper<Ts...> const& r) { return r.range.begin(); }
    template <typename ... Ts>
        auto end  (input_function_range_wrapper<Ts...>& r)       { return r.range.end  (); }
    template <typename ... Ts>
        auto end  (input_function_range_wrapper<Ts...> const& r) { return r.range.end  (); }
}

template <typename F, typename V = int>
auto make_input_function_range(F& f, V a, V b) {
    return detail::input_function_range_wrapper<F>(f, a, b);
}

#include <iostream>

int main() {
    auto f = [i=1]() mutable { return i*=2; };

    for (auto v : make_input_function_range(f, 0, 10)) {
        std::cout << v << " ";
    }
}

答案 1 :(得分:1)

对于error: no type named 'result_type',请参阅此bug

make_function_input_range写得很简单,但由于提到的错误,这不能用于普通的lambdas:

template<class T>
auto make_function_input_range(std::size_t begin, std::size_t end, T& f) {
    return boost::make_iterator_range(
        boost::make_function_input_iterator(f, begin),
        boost::make_function_input_iterator(f, end));
}

要解决这个问题,我会创建一个小助手类型来定义所需的result_type,而不是使用类型擦除std::function

template<class T>
struct fun_wrapper {
    T f;

    using result_type = typename boost::function_types::result_type<T>;
    template<class... Args>
    result_type operator() (Args&&... args) const {
        return f(std::forward<Args>(args)...);
    }
};

template<class T>
auto make_fun_wrapper(T&& f) {
    return fun_wrapper<T>{std::forward<T>(f)};
}

int main() {
    auto wrapped_f = make_fun_wrapper([](int i)->int {/*...*/});
    auto range = make_function_input_range(0, 10, wrapped_f);
}