Mixed list initialization in C++11 - c++

With reference to c++11 list initialization, may I initialize a list with an element and another list?
Let's say I have the following code:
#include <vector>
class Foo
{
public:
Foo(int value){m_v=value;}
private:
int m_v = 0;
};
int main()
{
std::vector<Foo> v1, v2, v3;
v1 = {Foo(1)}; //ok
v2 = {Foo(2), Foo(3)}; //ok
v3 = {Foo(3), v2}; //error: no match for ‘operator=’ (operand types are ‘std::vector’ and ‘’)
}
Is there a way to create in one line of code, using list initialization, a vector made of the element of another vector plus a new element (a prepend, in the example above).

We can create some template infrastructure to allow creation of vectors through optional concatenation of objects and other vectors.
This is very much a first cut:
#include <utility>
#include <vector>
namespace extended
{
template<class T>
struct appender
{
template<class V, class A, class Arg>
void operator()(std::vector<V, A>& vec, Arg&& arg) const
{
vec.push_back(std::forward<Arg>(arg));
}
};
template<class V2, class A2>
struct appender<std::vector<V2, A2>>
{
template<class V, class A, class X>
void operator()(std::vector<V, A>& vec, X&& arg) const
{
vec.insert(end(vec), begin(std::forward<X>(arg)), end(std::forward<X>(arg)));
}
};
template<class V, class A, class T>
auto append(std::vector<V, A>& target, T&& x) -> decltype(auto)
{
auto op = appender<std::decay_t<T>>();
op(target, std::forward<T>(x));
return target;
}
}
template<class T, class...Args>
auto make_vector(Args&&...args)
{
using extended::append;
std::vector<T> result;
using expand = int[];
expand {0,
(append(result, std::forward<Args>(args)), 0)...
};
return result;
}
class Foo
{
public:
Foo(int value){m_v=value;}
private:
int m_v = 0;
};
int main()
{
auto v1 = make_vector<Foo>(Foo(1)); //ok
auto v2 = make_vector<Foo>(Foo(2), Foo(3)); //ok
auto v3 = make_vector<Foo>(Foo(3), v2); //ok
}
Of course, by looking for common interfaces we can start to push the boundaries a little:
#include <utility>
#include <iterator>
#include <vector>
#include <list>
#include <set>
namespace extended
{
// The general case of an appender.
// simply calls emplace_back
template<class T, class Diff = void>
struct appender
{
template<class V, class A, class Arg>
void operator()(std::vector<V, A>& vec, Arg&& arg) const
{
vec.emplace_back(std::forward<Arg>(arg));
}
};
// specific specialisation for an appender where the
// source object supports begin() and end() (i.e. a container)
//
template<class T>
struct appender
<
T,
decltype(
std::begin(std::declval<T>()),
std::end(std::declval<T>()),
void()
)
>
{
template<class V, class A, class X>
void operator()(std::vector<V, A>& vec, X&& arg) const
{
vec.insert(std::end(vec), std::begin(std::forward<X>(arg)), std::end(std::forward<X>(arg)));
}
};
template<class V, class A, class T>
auto append(std::vector<V, A>& target, T&& x) -> decltype(auto)
{
auto op = appender<std::decay_t<T>>();
op(target, std::forward<T>(x));
return target;
}
}
template<class T, class...Args>
auto make_vector(Args&&...args)
{
using extended::append;
std::vector<T> result;
using expand = int[];
expand {0,
(append(result, std::forward<Args>(args)), 0)...
};
return result;
}
class Foo
{
public:
Foo(int value){m_v=value;}
bool operator<(const Foo& r) const { return m_v < r.m_v; }
private:
int m_v = 0;
};
int main()
{
auto v1 = make_vector<Foo>(Foo(1)); //ok
auto v2 = make_vector<Foo>(Foo(2), Foo(3)); //ok
auto v3 = make_vector<Foo>(Foo(3), v2); //ok
auto v4 = make_vector<Foo>(Foo(1),
std::list<Foo> { Foo(2), Foo(3) },
make_vector<Foo>(4, make_vector<Foo>(8, 9, 10)),
std::set<Foo> {Foo(6), Foo(7) }); // bizzare but ok
}

std::vector<Foo> means a std::vector of Foo instances. This means it cannot arbitrarily store other std::vector instances, which is what you're asking the compiler when writing
v3 = {Foo(3), v2};
std::initializer_list<T> is a homogeneous collection of T instances. std::vector<Foo>'s list constructor takes std::initializer_list<Foo>. There's no way to achieve what you want without manually unpacking v2's elements inside the curly braces.
Is there a way to create in one line of code, using list initialization, a vector made of the element of another vector plus a new element (a prepend, in the example above).
Using list initialization, no. You can write your own function to achieve the same thing, however.

Related

Initializing array in struct

Assume we have some templated struct and sometimes it's template should be an array. How to initialize array in struct?
This
template<typename T>
struct A {
T x;
A(T x) : x(x) {}
};
int a[6];
A<decltype(a)> b(a);
generates error during compilation:
error: array initializer must be an initializer list
A(T x) : x(x) {}
^
UPD1. More complete code this thing is used in:
template<typename T>
struct A {
T x;
A(const T& x) : x(x) {}
A(const T&& x) : x(std::move(x)) {}
};
template<typename T>
A<typename std::remove_reference<T>::type> make_A(T&& a) {
return A<typename std::remove_reference<T>::type>(std::forward<T>(a));
}
auto a = make_A("abacaba");
A general solution is to provide a special constructor for arrays (enabled when T is an array) which copies the source array to the struct's array. It works, but discard move semantics for arrays.
#include <iostream>
#include <type_traits>
#include <string>
#include <tuple>
template<typename T>
struct A {
using value_type = std::remove_const_t<T>;
value_type x;
template<class U=T> A(const T& src, std::enable_if_t<!std::is_array_v<U>, int> = 0) : x(src) {}
template<class U=T> A(const T&& src, std::enable_if_t<!std::is_array_v<U>, int> = 0) : x(std::move(src)) {}
template<class U=T> A(const T& src, std::enable_if_t< std::is_array_v<U>, int> = 0) { std::copy(std::begin(src), std::end(src), std::begin(x)); }
};
template<typename T>
auto make_A(T&& a)
{ return A<typename std::remove_reference_t<T>>(std::forward<T>(a)); }
int main()
{
auto a1 = make_A("the answer");
std::ignore = a1;
auto a2 = make_A(42);
std::ignore = a2;
}
live demo
If you need T to be const for non-arrays sometimes, an improvement would be to define value_type as T if T is not an array and to std::remove_const_t<T> otherwise.
I suggest putting all the smarts into make_A, converting C-arrays to std::array<>s so that A<> needs only work with regular types:
namespace detail {
template<typename T, std::size_t... Is>
constexpr std::array<T, sizeof...(Is)> to_std_array(T const* const p,
std::index_sequence<Is...>)
{
return {{p[Is]...}};
}
}
template<typename T>
A<std::decay_t<T>> make_A(T&& x) {
return {std::forward<T>(x)};
}
template<typename T, std::size_t N>
A<std::array<T, N>> make_A(T const (& x)[N]) {
return {detail::to_std_array(x, std::make_index_sequence<N>{})};
}
Online Demo
If you're only concerned with hardcoded C-strings in particular (as opposed to C-arrays in general), consider converting to a string_view type rather than std::array<> to potentially save some space.
If it is a special behaviour you want to achieve for C-Strings exclusively, you may just add a special treatment:
// for all non-C-string cases
template<typename T, std::enable_if_t<!std::is_same_v<std::decay_t<T>, const char*>>* = nullptr>
A<typename std::remove_reference<T>::type> make_A(T&& a) {
return A<typename std::remove_reference<T>::type>(std::forward<T>(a));
}
// in case a C-string got passed
A<std::string> make_A(const std::string& str) {
return A<std::string>(str);
}
int main()
{
auto a = make_A("abacaba");
auto b = make_A(5);
}
With std::decay it works:
template<typename T>
A<typename std::decay<T>::type> make_A(T&& a) {
return A<typename std::decay<T>::type>(std::forward<T>(a));
}

Make function generic with respect to pointers and references

Suppose I have this C++ function:
class C { ... };
void do(const vector<C>& cs) {
...
for (...) {
cs[i].do_whatever();
}
...
}
But C is expensive to copy so I might have something like this:
std::vector<C*> reorder_in_some_way(const std::vector<C>& cs) {
...
}
int main() {
std::vector<C> cs = ...;
std::vector<C*> reorderedCs = reorder_in_some_way(cs);
do(reorderedCs);
}
Obviously this won't work. I could get around it by giving up and just making do a template over any type like this:
template<typename T>
void do(const vector<T>& cs) {
But it really only works with C's and I'd like that to be encoded in the type system - and also it makes do() easier to understand if you don't have to go hunting around for places where it is used.
Is there any way to write do() so that it can generically take both vector<C> and vector<C*> (and for bonus points vector<reference_wrapper<C>>)?
Just write 2 template functions that applies a functor:
template<class T,typename Func>
void apply( const std::vector<T> &v, Func f )
{
for( const auto &i : v ) f( i );
}
template<class T,typename Func>
void apply( const std::vector<T*> &v, Func f )
{
for( auto i : v ) f( *i );
}
then pass a lambda:
std::vector<C> vc;
std::vector<C*> vp;
auto call = []( const C &c ) { c.do_whatever(); };
apply( vc, call );
apply( vp, call );
(note you cannot call your function do - it is a keyword in C++)
live example
PS As you mentioned in comments your function apply is rather complex so you prefer to have only one copy of it, in this case create a helper:
template<class T>
const T &apply_helper( const T *t ) { return *t; }
template<class T>
typename std::enable_if<!std::is_pointer<T>::value, const T &>::type
apply_helper( const T &t ) { return t; }
then write your apply function only once:
template<class T,typename Func>
void apply( const std::vector<T> &v, Func f )
{
for( const auto &i : v ) f( apply_helper( i ) );
}
live example N2
You might keep your do function generic, but specialize a getter for T& and T* that both return a T&:
namespace detail{
template<class T>
T& get(T& _in){
return _in;
}
template<class T>
T& get(T* _in){
return *_in;
}
} // namespace detail
template<class T>
void do_a_thing(const std::vector<T>& cs) {
for (size_t i = 0; i < cs.size(); ++i) {
detail::get(cs[i]).do_whatever();
}
}
Demo
Either way you are going to need to specialize between pointers and references. I think that this pushes it to the smallest scope.
If you want to constrain do_a_thing to only accept C or C*, we can create a small trait to do this:
template <class T>
struct is_c : std::false_type{};
template <>
struct is_c<C>: std::true_type{};
template <>
struct is_c<C*>: std::true_type{};
And then modify do_a_thing with std::enable_if:
template<class T, std::enable_if_t<is_c<T>::value, int> = 0>
void do_a_thing(const std::vector<T>& cs) {
for (size_t i = 0; i < cs.size(); ++i) {
detail::get(cs[i]).do_whatever();
}
}
For bonus points, we'll write another specialization of do_a_thing that gives a nice compiler error for types that do not satisfy the constraint:
template<class T>
struct always_false : std::false_type{};
template<class T, std::enable_if_t<!is_c<T>::value, int> = 0>
void do_a_thing(const std::vector<T>& cs) {
static_assert(always_false<T>::value, "do_a_thing only works for C and C*");
}
Now the following will fail:
struct Q{};
std::vector<Q> qs;
do_a_thing(qs); // compiler error
Demo
Write a function template that gets a pair of iterators (not a vector).
Then pass it either normal vector<C>::iterators, or adapted vector<C*>::iterators, e.g. boost::transform_iterator instances.
Working example:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <boost/iterator/transform_iterator.hpp>
int& deref(int*& x) { return *x; }
template <class it>
void print(it from, it to)
{
std::copy(from, to, std::ostream_iterator<typename it::value_type>(std::cout, " "));
std::cout << "\n";
}
int main()
{
std::vector<int> a {4,3,7,1};
std::vector<int*> b {new int(2), new int(0), new int(11), new int(-3)};
// auto deref = [](int*& x) -> int& { return *x; };
// cannot use a lambda here because it's non-copyable
// and iterators must be copyable.
std::sort(std::begin(a), std::end(a));
std::sort(boost::make_transform_iterator(std::begin(b), &deref),
boost::make_transform_iterator(std::end(b), &deref));
print(std::begin(a), std::end(a));
print(boost::make_transform_iterator(std::begin(b), &deref),
boost::make_transform_iterator(std::end(b), &deref));
}
I think a possible solution could be to create a modified vector class that is generic with respect to pointerness, and can be implicitly converted to from a vector<T> or a vector<T*>. Like this:
template<typename T>
class VectorWrapper {
public:
VectorWrapper(const vector<T>& v) : reference(&v) { }
VectorWrapper(const vector<T*>& v) : pointer(&v) { }
const T& at(int idx) const {
if (reference)
return (*reference)[idx];
return *(*pointer)[idx];
}
// etc. for size() and so on. You could probably have
// this class derive from std::vector and reimplement its
// methods to switch between `reference` and `pointer`.
private:
const vector<T>* reference = nullptr;
const vector<T*>* pointer = nullptr;
};
void do_thing(VectorWrapper<C> wrapper) {
wrapper.at(0).whatever();
}
Not tested, and I don't think I'll go this route to be honest but it's the best I could come up with.

C++ passing parameter pack to class

I'd like to have a class that gets in it's Ctor unlimited parameters of the same type, and stores them into a vector. It should look like that:
class A(int a, int b, **N time parameter of type T**)
: data(**vector will get N times type T**)
{
}
protected:
vector<T> data;
How should I implement it? Solution could be in c++11/14
I got a few errors such as "parameter packs not expanded with ‘…' ", etc..
This code sample might be useful:
#include <vector>
#include <utility>
template<typename T>
class MyClass {
public:
template<typename ...Args>
MyClass(int a, int b, Args&& ...args) :data{ std::forward<Args>(args)... } {}
private:
std::vector<T> data;
};
int main() {
MyClass<char> sample(1, 2, 'a', 'b');
return 0;
}
[EDIT]: Added std::forward, added missing include for utility
Assuming that T could be anything, even something quite large or non-copyable, we'd want to:
preserve efficiency with perfect forwarding.
check types.
std::initializer_list satisfies 2 but not 1.
Simple variadic template expansion satisfies 1 and not 2.
This solution uses variadic template expansion and enable_if to enforce type compatibility.
#include <vector>
#include <utility>
#include <string>
namespace detail
{
constexpr bool all()
{
return true;
}
template<class...Rest>
constexpr bool all(bool b, Rest...rest)
{
return b and all(rest...);
};
}
template<class T>
class A
{
public:
using value_type = T; // say
template<class...Rest,
std::enable_if_t<detail::all(std::is_convertible<Rest, value_type>::value...)>* = nullptr>
A(int a, int b, Rest&&...rest)
: a_(a), b_(b)
{
this->fill(std::forward_as_tuple(std::forward<Rest>(rest)...),
std::make_index_sequence<sizeof...(Rest)>());
}
private:
template<class Tuple, std::size_t...Is>
void fill(Tuple&& t, std::index_sequence<Is...> seq)
{
data_.reserve(seq.size());
using expand = int[];
void(expand{ 0,
(data_.push_back(std::move(std::get<Is>(t))), 0)...
});
}
private:
int a_, b_;
std::vector<value_type> data_;
};
int main()
{
using namespace std::literals;
auto a = A<double>(1, 2, 4.3, 5.5, 6.6);
auto b = A<std::string>(1, 2, "the", "cat"s, "sat on the mat");
// error: no matching constructor...
// auto err = A<std::string>(1, 2, "the", "cat"s, 0.1);
}
Here you go:
#include <iostream>
#include <vector>
template<class T>
struct V
{
V(int n, std::initializer_list<T> l)
: data(l)
{
(void) n;
}
std::vector<T> data;
};
int main()
{
V<int> v(0,{1,2,3});
}
This is not a perfect example since one needs to construct an object with the weird syntax (n, {optional, arguments, of, same, type}) but it does provide wanted behavior.
The following example is similar to fr3nzy90's, but with the coming C++17 it will allow automatic deduction of T from the constructor arguments:
template <class T>
class MyContainer {
private:
std::vector<T> data;
public:
// Take the first T value explicitly so it can be used to deduce
// T from the constructor arguments (C++17 feature).
template <class... Ts>
MyContainer(int a, int b, T const & tval, Ts const &... tvals) :
data{tval, tvals...} {
…
}
// Special case, empty list, no implicit type deduction, because
// there is no T value to deduce it from.
MyContainer(int a, int b) {
…
}
};

std set of boost::shared_ptr<string>

I have a set of boost::shared_ptr which I want to be ordered and uniqued not by the shared pointers but by the strings. Do I have to provide a new comparison function getting shared pointers and comparing the contents or there is such a comparator already exists that I can use?
That's pretty specific, so you'll probably need a custom comparator.
This should work:
struct pointercompare
{
bool operator()(const boost::shared_ptr<std::string>& a, const boost::shared_ptr<std::string>& b)
{
return (*a)>(*b);
}
}
I would write a general way of wrapping predicates and iterators that maps value-semantics onto any pointer-like owner.
This then becomes completely general and re-usable.
Simple version here
Bonus code below introduces a complete library for this kind of thing
#include <utility>
#include <boost/shared_ptr.hpp>
#include <vector>
#include <algorithm>
template<class Comp>
struct pointee
{
pointee(Comp comp = Comp()) : _comp(comp) {}
template<class APtr, class BPtr>
bool operator()(const APtr& a, const BPtr& b)
{
return _comp(*a, *b);
}
Comp _comp;
};
int main()
{
std::vector<boost::shared_ptr<int>> v;
std::sort(v.begin(), v.end(), pointee<std::less<>>());
std::sort(v.begin(), v.end(), pointee<std::greater<>>());
}
For bonus points...
#include <utility>
#include <boost/shared_ptr.hpp>
#include <vector>
#include <algorithm>
#include <functional>
template<class T, class X, class Y>
struct is_binary_op
{
template<class U> static auto test(U* p) -> decltype((*p)(std::declval<X>(), std::declval<Y>()), void(), std::true_type());
template<class U> static auto test(...) -> decltype(std::false_type());
static constexpr bool value = decltype(test((T*)0))::value;
};
template<class T, class X, class Y> static constexpr bool IsBinaryOp = is_binary_op<T, X, Y>::value;
template<class T, class X>
struct is_unary_op
{
template<class U> static auto test(U* p) -> decltype((*p)(std::declval<X>()), void(), std::true_type());
template<class U> static auto test(...) -> decltype(std::false_type());
static constexpr bool value = decltype(test((T*)0))::value;
};
template<class T, class X> static constexpr bool IsUnaryOp = is_unary_op<T, X>::value;
namespace detail {
template<class Comp>
struct pointee
{
pointee(Comp comp = Comp()) : _comp(comp) {}
template<
class APtr,
class BPtr
>
auto operator()(const APtr& a, const BPtr& b) const
-> std::enable_if_t<
IsBinaryOp<Comp, decltype(*a), decltype(*b)>
, bool>
{
return _comp(*a, *b);
}
template<
class APtr
>
auto operator()(const APtr& a) const
-> std::enable_if_t<
IsUnaryOp<Comp, decltype(*a)>
, bool>
{
return _comp(*a);
}
Comp _comp;
};
template<class Iter>
struct deref_iter : Iter
{
deref_iter(Iter iter) : Iter(iter) {}
auto& operator*() const {
return **static_cast<const Iter&>(*this);
}
};
}
template<class Pred>
auto pointee(Pred&& pred)
{
return detail::pointee<std::decay_t<Pred>>(std::forward<Pred>(pred));
}
template<class Iter>
auto deref_pointee(Iter&& iter)
{
return detail::deref_iter<std::decay_t<Iter>>(std::forward<Iter>(iter));
}
int main()
{
std::vector<boost::shared_ptr<int>> v;
// sort using the less predicate on the pointee
std::sort(v.begin(), v.end(), pointee(std::less<>()));
// sort using the greater predicate on the pointee
std::sort(v.begin(), v.end(), pointee(std::greater<>()));
// apply a unary predicate to every pointee
std::for_each(v.begin(), v.end(), pointee(std::logical_not<>()));
// transform the pointees by binding a binary predicate to a value and
// turning it into a unary predicate that adds 6
std::transform(v.begin(), v.end(),
deref_pointee(v.begin()),
pointee(std::bind(std::plus<>(), 6, std::placeholders::_1)));
}

Shortcut syntax for boost function_input_iterator range

I am wondering if there is a shortcut syntax for this sort of code:
#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;
}
Two notes:
I couldn't use auto f = [](int i) ->int {...}; as this causes:
error: no type named 'result_type' in 'struct main()::<lambda(int)>'
using std::function fixes it for some reason.
Also I can't pass f as temporary inline ie boost::make_function_input_iterator([](int i) ->int {...}, ... as that function takes f by reference.
Ideally I'd like to be able to do:
make_function_input_range(0, 10, [](int i)->int {...});
You could use a trivial wrapper that adds the 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. I use a reference wrapper to stay with function_input_iterator's requirements, which already require the function to be an lvalue reference. You could leave this behind now, actually, since we return the function wrapper as well as the range, see below
Next up, have a helper that returns a tuple of that wrapper and the iterator-range built on it:
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))
{ }
};
To make using it convenient, lets move it into a detail namespace and add a factory function:
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);
}
Now to really top it off, we add ADL-enabled begin and end calls and PRONTO, we can use c++'s ranged-for on it:
int main() {
auto f = [i=1]() mutable { return i*=2; };
for (auto v : make_input_function_range(f, 0, 10)) {
std::cout << v << " ";
}
}
Prints
2 4 8 16 32 64 128 256 512 1024
FULL DEMO
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 << " ";
}
}
For the error: no type named 'result_type', refer to this bug.
make_function_input_range is trivial to write, but this cannot be used with plain lambdas, because of the mentioned bug:
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));
}
To work around the bug, I would create a small helper type that defines the required result_type, rather than use the type-erasing 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);
}