我想知道这种代码是否有快捷语法:
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 {...}, ...
答案 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的begin
和end
调用以及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);
}