I am currently trying to use std::bind to create a std::function<void()> from the function template
template<class Iterator>
void printRange(Iterator first, Iterator last) {
std::copy(first, last, std::ostream_iterator<typename Iterator::value_type>(std::cout, " "));
std::cout << std::endl;
}
Conceptually, what I want is
int main() {
std::vector<int> v{1, 2, 3};
auto f0 = std::bind(printRange, v.begin(), v.end()); // won't compile, of course
f0();
return 0;
}
I understand that this does not compile and I have to instantiate the function template before I can actually use it. For example, the following alternatives would work:
auto f1 = std::bind(printRange<std::vector<int>::const_iterator>, v.begin(), v.end());
auto f2 = std::bind(printRange<decltype(v.begin())>, v.begin(), v.end());
auto f3 = [&v]() { printRange(v.begin(), v.end()); };
I already created a convenience function
template<class Iterator>
std::function<void()> makePrintRangeFunction(Iterator first, Iterator last) {
return std::bind(printRange<Iterator>, first, last);
}
to ease the process:
auto f4 = makePrintRangeFunction(v.begin(), v.end());
I wonder if it is possible to create a more generic std::function<void()> generator, accepting a function template as a first argument and the function template arguments as a variable-length argument list? If not using built-in language features, maybe via a macro?
As long as you do not need to have template function return type, you can do this:
#include <functional>
#include <iostream>
#include <typeinfo>
template<typename ... T>
std::function<void()> makePrintRangeFunction(void (*f)(T...), T... param) {
return std::bind(f, param...);
}
template<typename T, typename V>
void print(T type, V val)
{
std::cout << typeid(type).name() << '\n' << val << '\n';
}
int main()
{
int i = 5;
double d = 10.5;
auto f = makePrintRangeFunction(print, i, d);
f();
}
Maybe the following code will help :)
template <class F, class... Args>
void test(F&& f, Args&&... args) {
std::function<typename std::result_of<F(Args...)>::type()> task(
std::bind(std::forward<F>(f), std::forward<Args>(args)...));
task();
}
If your compiler supports C++14 you could define a generic lambda wrapper as:
template<typename F>
auto fungen(F f) {
return [=](auto... args) { f(args...); };
}
Use case:
int main() {
std::vector<int> v {1, 2, 3, 4};
auto f = fungen(printRange<std::vector<int>::iterator>);
f(v.begin(), v.end());
}
Live Demo
Related
I'd like to write a helper function like:
template <typename F, typename Range1, typename Range2>
auto helper(const Range1& left, const Range2& right, F&& pred)
{
using namespace std; // for cbegin/cend and ADL
return pred(cbegin(left), cend(left), cbegin(right), cend(right));
}
It works well for containers:
std::vector<int> v1 = {1,2,3,4,5,6};
std::vector<int> v2 = {5,4,3,2,1,6};
std::cout << helper(v1, v2, [](const auto&... args){ return std::is_permutation(args...);}) << std::endl;
but it fails to deduce initializer_list-s (example):
std::cout << helper({1,2,3,4,5,6}, {5,4,3,2,1,6}, [](const auto&... args){ return std::is_permutation(args...);}) << std::endl;
Is there an idiomatic way to rewrite helper so that it deduces both containers and initializer_list-s?
I can't come up with anything better than overloads for all combinations of container and initializer_list.
I think the fundamental problem here is that a braced-init-list like { 1, 2, 3 } is just an initializer and not an object of type std::initializer_list<T>. It can potentially be used to initialize an object of some given type. But it's not an object of any type itself. And there doesn't seem to be anything in the rules for function template argument deduction that would allow you to get an std::initializer_list<T> from a braced-init-list argument unless your function parameter was already declared to be some sort of std::initializer_list<T> to begin with.
So I'm afraid writing those overloads will be the simplest solution…
Here is the best I can do:
template<class X>
struct Range {
X* container;
Range(X& x):container(std::addressof(x)) {}
Range(X&& x):container(std::addressof(x)) {} // dangerous, but hey
auto begin() const { using std::begin; return begin(*container); }
auto end() const { using std::end; return end(*container); }
auto cbegin() const { using std::cbegin; return cbegin(*container); }
auto cend() const { using std::cend; return cend(*container); }
};
template<class T>
struct Range<std::initializer_list<T>> {
using X=std::initializer_list<T>;
X container;
Range(X x):container(x) {}
auto begin() const { using std::begin; return begin(container); }
auto end() const { using std::end; return end(container); }
auto cbegin() const { using std::cbegin; return cbegin(container); }
auto cend() const { using std::cend; return cend(container); }
};
template<class T>
Range( std::initializer_list<T> ) -> Range<std::initializer_list< T >>;
template<class C1, class C2>
void foo( Range<C1> r1, Range<C2> c2 ) {}
test code:
Range r = {{'a', 'b', 'c'}};
(void)r;
std::vector v = {1,2,3};
foo( Range{{'a','b','c'}}, Range{v} );
you have to cast the arguments to Range manually for this to work at the call site, because class template arguement deduction doesn't work on function arguments.
We might be able to attack it differently.
template <typename F, typename Range1, typename Range2>
auto helper(const Range1& left, const Range2& right, F&& pred)
change the above syntax to a chained-call.
helper(v1)({1,2,3})[pred];
that reduces the 2^n explosion into 2. Not much of a help with 2 overloads, but still...
template<class...Ts>
struct helper_t {
std::tuple<Ts&&...> containers;
template<class T>
helper_t<T, Ts...> operator()(T&& t)&& {
return { /* append-move containers and t into one tuple */ };
}
template<class T>
helper_t<std::initializer_list<T>, Ts...> operator()(std::initializer_list<T> t)&& {
return { /* append-move containers and t into one tuple */ };
}
template<class F>
decltype(auto) operator[](F&& f)&& {
return std::move(*this).apply_impl(
std::make_index_sequence<sizeof...(Ts)>{},
std::forward<F>(f)
);
}
private:
template<std::size_t...Is, class F>
decltype(auto) apply_impl( std::index_sequence<Is...>, F&& f ) && {
using std::cbegin; using std::cend;
using std::get;
return std::forward<F>(f)(
cbegin( get<Is>(std::move(containers)) ), cend( get<Is>(std::move(containers)) )
);
}
};
static constexpr const helper_t<> helper;
I left appending the tuples as an exercise.
helper( container1 )( {1,2,3} )( container2 )[ some_lambda ];
is the syntax.
Please explicitly specify that the arguments you are passing is the initializer_list like this:-
std::cout << helper(v1, std::initializer_list<int>{5,4,3,2,1,6}, [](const auto&... args){ return std::is_permutation(args...);}) << std::endl;
std::cout << helper(std::initializer_list<int>{1,2,3,4,5,6}, std::initializer_list<int>{5,4,3,2,1,6}, [](const auto&... args){ return std::is_permutation(args...);}) << std::endl;
This is the way you can pass the initializer_list else you need to overload for all combinations of container and initializer_list
As explained by Michael Kenzel, the problem is that a braced-init-list isn't an std::intializer_list.
So I'm agree with Michael (+1): I don't see a way to write a single template function that can deduce both STL containers and (as std::initilizer_list<T>) braced-init-lists.
But if you can accept to add an helper() helper function for your helper() function, you can use the fact that a braced-init-list can be deduced as a C-style array.
So you can write a helper() specific version for C-style arrays that can convert the C-style arrays in std::initializer_list (or std::array, or... see you) or, in my example, you can simply call your original helper() function passing the arrays but explicating the types.
I mean: you can add this helper() helper function
template <typename F, typename R1, std::size_t S1,
typename R2, std::size_t S2>
auto helper (R1 const (&r1)[S1], R2 const (&r2)[S2], F && pred)
{ return helper<F, R1[S1], R2[S2]>(r1, r2, std::forward<F>(pred)); }
Drawback: this works if both ranges are STL containers or if both ranges are C-style arrays (or braced-init-lists); if you can have a STL container and a C-style array, you have to write other two helper() helper function: one for (only) the first range and one for (only) the second.
The following is a full working example
#include <vector>
#include <iostream>
#include <algorithm>
template <typename F, typename Range1, typename Range2>
auto helper (Range1 const & left, Range2 const & right, F && pred)
{ return pred(std::cbegin(left), std::cend(left),
std::cbegin(right), std::cend(right)); }
template <typename F, typename R1, std::size_t S1,
typename R2, std::size_t S2>
auto helper (R1 const (&r1)[S1], R2 const (&r2)[S2], F && pred)
{ return helper<F, R1[S1], R2[S2]>(r1, r2, std::forward<F>(pred)); }
int main ()
{
std::vector<int> v1 = {1,2,3,4,5,6};
std::vector<int> v2 = {5,4,3,2,1,6};
std::cout << helper(v1, v2,
[](auto const & ... args){ return std::is_permutation(args...);})
<< std::endl;
std::cout << helper({1, 2, 3, 4, 5, 6}, {5, 4, 3, 2, 1, 6},
[](auto const &... args){ return std::is_permutation(args...);})
<< std::endl;
}
I found myself needing to iterate (generically) over an array, or a tuple of N T's.
Code demo:
http://coliru.stacked-crooked.com/a/9b8ab7c01b79d086
I came up with the following implementation, which I'm reasonably happy with it, as it seems to to handle the cases I need without introducing any overhead.
#include <array>
#include <iostream>
#include <tuple>
#include <vector>
namespace functional
{
namespace detail {
template <typename Tuple, typename F, std::size_t... Indices>
void
tuple_for_each_impl(Tuple &&tuple, F &&f, std::index_sequence<Indices...>)
{
using swallow = int[];
(void)swallow{1, (f(std::get<Indices>(std::forward<Tuple>(tuple))), void(), int{})...};
}
} // ns detail
template <typename Tuple, typename F>
void
for_each(Tuple &&tuple, F &&f)
{
constexpr std::size_t N = std::tuple_size<std::remove_reference_t<Tuple>>::value;
detail::tuple_for_each_impl(std::forward<Tuple>(tuple), std::forward<F>(f), std::make_index_sequence<N>{});
}
} // ns functional
struct tuple_tag {};
struct iterator_tag {};
template<typename U, typename TAG>
struct burrito
{
U value;
using TAG_TYPE = TAG;
template<typename T>
burrito(T const& t) : value(t) {}
template<typename T>
burrito(T t0, T t1) : value(std::make_pair(t0, t1)) {}
template<typename FN>
void iterate(FN const fn) const
{
bool constexpr IS_TUPLE = std::is_same<tuple_tag, TAG_TYPE>();
if constexpr (IS_TUPLE) {
functional::for_each(this->value, fn);
} else {
for (auto it{value.first}; it < value.second; ++it) {
fn(*it);
}
}
}
};
template<typename M, typename FN>
void testfn(M const& m, FN const& fn)
{
m.iterate(fn);
}
template<typename T>
auto
make_burrito(T t0, T t1)
{
auto const p = std::make_pair(t0, t1);
return burrito<decltype(p), iterator_tag>{p};
}
template<typename C>
auto
make_burrito(C const& c)
{
return make_burrito(c.cbegin(), c.cend());
}
template<typename ...T>
auto
make_burrito(std::tuple<T...> const& t)
{
using U = std::tuple<T...>;
return burrito<U, tuple_tag>{t};
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// demo
int main()
{
std::tuple<int, int> const tup0 = std::make_tuple(-3, -4);
std::array<int, 10> const arr0 = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
std::vector<int> const v = {32, 42, 52, 62};
auto const m0 = make_burrito(tup0);
auto const m1 = make_burrito(arr0.begin(), arr0.end());
auto const m2 = make_burrito(v);
auto const fn = [](auto const& i) {
std::cerr << std::to_string(i) << "\n";
};
std::cerr << "printing tuple\n";
testfn(m0, fn);
std::cerr << "|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-" << "\n";
std::cerr << "printing array\n";
testfn(m1, fn);
std::cerr << "|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-" << "\n";
std::cerr << "printing vec\n";
testfn(m2, fn);
std::cerr << "|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-" << "\n";
}
I'd like to be able to hide the instantiation of the burrito from the caller entirely, but still define my function arguments as a burrito.
Like this:
template<typename B, typename FN>
void something(B const& burrito_like, FN const& fn) {
burrito_like.iterate(fn);
}
With the caller doing:
auto const tup = ...; // somehow caller creates a tuple
something(tup, []() {});
This doesn't work though (obviously) and the compiler complains about tuple not implement iterate(FN const&);
I looked into implicit conversion constructors, but I don't see how I would specify the different TAG parameters from within the implicit constructor.
So my question is, is something like this possible?
I'd like to write a class test that is able to store a function that is able to iterate through a collection of elements identified by the classic [first,last) iterator pair, that is:
template <typename T>
struct sum
{
template <typename I>
T operator()(I first, I last) const
{
T res = 0;
while (first != last)
{
res += *first;
++first;
}
return res;
}
};
//...
int main()
{
test<double> t;
t.set(sum<double>);
double a[] {1.,2.,3.};
std::cout << "Test (array) => " << t.call(a, a+3) << std::endl;
std::vector<double> v {1.,2.,3.};
std::cout << "Test (vector) => " << t.call(v.begin(), v.end()) << std::endl;
std::list<double> l {1.,2.,3.};
std::cout << "Test (list) => " << t.call(l.begin(), l.end()) << std::endl;
}
I thought to use std::function, but I've failed to do this as I wasn't able to declare the templated iterator pair.
A possible workaround is the following, which however only works with plain arrays (e.g., double[] or double*, like the above variable a), but not with other containers (e.g., like the above variables v and l):
template <typename T>
class test
{
public:
template <typename F>
void set(F f)
{
f_ = f;
}
template <typename I>
T call(I first, I last) const
{
return f_(first, last);
}
private:
std::function<T(T*,T*)> f_;
};
Any idea on how can I get the correct behavior?
NOTE: I'm compiling with GCC 4.9.2 --std=c++11
Thank you very much.
What you want is really to be able to construct a:
std::function<T(FwdIter<T>, FwdIter<T>)>
where FwdIter<T> is some type-erased class that satsifes the ForwardIterator concept and is dereferenced to a T. For that, check out the Boost.TypeErasure library, where we can do:
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/operators.hpp>
#include <boost/mpl/vector.hpp>
using namespace boost::type_erasure;
template <typename T>
using FwdIter = any<
boost::mpl::vector<
copy_constructible<>,
incrementable<>,
dereferenceable<T>,
equality_comparable<>
>>;
With that and your definition of sum, I can do:
std::function<int(FwdIter<int>, FwdIter<int>)> f = sum<int>{};
std::vector<int> v = {1, 2, 3, 4, 5};
std::cout << f(v.begin(), v.end()) << std::endl; // prints 15
In your test<T>, you could just have a std::function<T(FwdIter<T>, FwdIter<T>)> member as desired.
I've tried to work on an alternative solution.
Essentially, the user function is wrapped inside a holder holder which fix the function signature to T(const std::vector<T>&). With respect to #Barry's solution (the one I've accepted), this doesn't require external libraries. However it suffers of performance issues due to the construction of the vector object at runtime. Also, and more importantly, as pointed out by #Barry, this solution imposes artificial requirements on T (like T must be copyable).
Here is it:
template <typename T,typename F>
class holder
{
public:
holder(F f) : f_(f) { }
T operator()(const std::vector<T>& v) const
{
return f_(v.begin(), v.end());
}
private:
F f_;
};
template <typename T>
class test_v2
{
public:
template <typename F>
void set(F f)
{
f_ = holder<T,F>(f);
}
template <typename I>
T call(I first, I last) const
{
return f_(std::vector<T>(first, last));
}
private:
std::function<T(const std::vector<T>&)> f_;
};
Why not stoke the functor instead, something like:
template <typename T>
class test
{
public:
template <typename I>
auto call(I first, I last) const
-> decltype(T()(first, last))
{
return T()(first, last);
}
};
And use it:
test<sum<double>> t;
Live example
Consider this standard use of std::transform algorithm:
vector<int> in = { 1, 2, 3 };
auto f0 = [](int val) { return val + 1; };
auto f1 = [](int val) { return val > 1; };
vector<int> out0(in.size());
std::transform(in.begin(), in.end(), out0.begin(), f0);
vector<bool> out1(in.size());
std::transform(in.begin(), in.end(), out1.begin(), f1);
This works fine but is long to write. I would like to write something like this:
auto out0 = tranform(in, f0);
auto out1 = tranform(in, f1);
How to overload the transform algorithm to allow this syntax?
The following should do what you want
#include <algorithm>
#include <iostream>
#include <type_traits>
#include <vector>
template<typename T, typename F>
std::vector<typename std::result_of<F(T)>::type>
transform(const std::vector<T>& l, F func)
{
typedef typename std::result_of<F(T)>::type FunctorReturnType;
std::vector<FunctorReturnType> out(l.size());
std::transform(l.begin(), l.end(), out.begin(), func);
return out;
}
int main ()
{
const std::vector<int> in{ 1, 2, 3 };
auto f0 = [](int val) { return val + 1; };
auto f1 = [](int val) { return val > 1; };
auto out0 = transform(in, f0);
auto out1 = transform(in, f1);
for (const auto& m: out0) std::cout << m << std::endl;
for (const auto& m: out1) std::cout << m << std::endl;
}
Do you like template template arguments? This works with more containers than vectors.
template<template<class...> class C, class F, class T, class... Tail>
C<typename result_of<F(T)>::type>
transform(const C<T, Tail...>& in, F func)
{
C<typename result_of<F(T)>::type> out(in.size());
std::transform(in.begin(), in.end(), out.begin(), func);
return out;
}
Can be seen working at http://coliru.stacked-crooked.com/a/767adb662d7cbe42
EDIT: changed to not use the source's allocator in the resulting container.
Why aren't you ok with the following, which doesn't use any C++11 magic such as decltype ?
#include <algorithm>
#include <vector>
template<class T, class F>
std::vector<T> transform(const std::vector<T>& l, F func)
{
std::vector<T> out(l.size());
std::transform(l.begin(), l.end(), out.begin(), func);
return out;
}
I have the next code:
object a,b,c;
fun (a);
fun (b);
fun (c);
I wonder if it is there any way to do something similar in C++98 or C++11 to:
call_fun_with (fun, a, b, c);
Thanks
Here a variadic template solution.
#include <iostream>
template < typename f_>
void fun( f_&& f ) {}
template < typename f_, typename head_, typename... args_>
void fun( f_ f, head_&& head, args_&&... args) {
f( std::forward<head_>(head) );
fun( std::forward<f_>(f), std::forward<args_>(args)... );
}
void foo( int v ) {
std::cout << v << " ";
}
int main() {
int a{1}, b{2}, c{3};
fun(foo, a, b, c );
}
You may use the following using variadic template:
template <typename F, typename...Ts>
void fun(F f, Ts&&...args)
{
int dummy[] = {0, (f(std::forward<Ts>(args)), 0)...};
static_cast<void>(dummy); // remove warning for unused variable
}
or in C++17, with folding expression:
template <typename F, typename...Ts>
void fun(F&& f, Ts&&...args)
{
(static_cast<void>(f(std::forward<Ts>(args))), ...);
}
Now, test it:
void foo(int value) { std::cout << value << " "; }
int main(int argc, char *argv[])
{
fun(foo, 42, 53, 65);
return 0;
}
Using C++ 11, you can use std::function, this way (which is quite quick to write IMO)
void call_fun_with(std::function<void(int)> fun, std::vector<int>& args){
for(int& arg : args){
fun(arg);
}
}
or, a bit more generic:
template<typename FTYPE>
void call_fun_with(FTYPE fun, std::vector<int>& args){
for(int& arg : args){
fun(arg);
}
}
Live example
Live example, templated version
Note: std::function template arguments must be specified the following way: return_type(arg1_type, arg2_type,etc.)
EDIT: An alternative could be using std::for_each which actually does pretty much the same thing, but which I do not really like as to the semantics, which are more like "for everything in this container, do...". But that's just me and my (maybe silly) way of coding :)
A C++11 range-based (enhanced) for loop will recognise a braced-init-list as an initializer_list, which means something like the following will work:
for (auto &x : {a,b,c}) fun(x);
there are a lot of different way's...
#include <iostream>
#include <vector>
#include <algorithm>
void foo(int x) {
std::cout << x << "\n";
}
void call_fun_with(std::function<void(int)> fn, std::vector<int> lst) {
for(auto it : lst)
fn(it);
}
int main() {
std::vector<int> val = {1,2,3,4,5};
// c++98
std::for_each(val.begin(), val.end(), foo);
// c++11
// vector
call_fun_with(foo, val);
// c++11
// initializer_list
int a=0, b=1, c=2;
call_fun_with(foo, {a,b,c});
}
see here.