3

I'm trying to learn the new features of C++11 and I have this code:

void print(int t, string separator)
{
    cout << t << separator;
}


int elements[] = { 10, 20, 30, 40, 50, 60, 40 };
string delim = " - ";

for_each(elements, elements + 7, bind2nd(ptr_fun(print), delim));

Output:

10 - 20 - 30 - 40 - 50 - 60 - 40 -

About ptr_fun, this site says:

This function and the related types are deprecated as of C++11 in favor of the more general std::function and std::ref, both of which create callable adapter-compatible function objects from plain functions.

Can someone rewrite the example above without ptr_fun and with the functions recomended for C++11?

Thank you

user7140484
  • 920
  • 6
  • 14
  • I think most would probably prefer an `std::ostream_iterator` in this case, totally obviating the `std::function` usage. YMMV depending on application. :) See [here](http://ideone.com/yJnbFo). – erip Nov 13 '16 at 16:14

2 Answers2

7

The most C++11 way would probably be to use a lambda (or a ranged for)

for_each(elements, elements + 7, [&delim](int val){ print(val, delim); });

demo

ranged for:

for(int x : elements)
    print(x, delim);

demo

You could use std::bind:

for_each(elements, elements + 7, bind(print, placeholders::_1, delim));

demo

But in this case, you could rewrite the whole thing as

copy(elements, elements + 7, ostream_iterator<int>(cout, delim.c_str()));

demo


If you absolutely want to use std::function, you can modify the above examples to do so:

for_each(elements, elements + 7, function<void(int)>([&delim](int val){ print(val, delim); }));

for_each(elements, elements + 7, function<void(int)>(bind(print, placeholders::_1, delim)));

It is pretty pointless unless you need type-erasure, though.

krzaq
  • 16,240
  • 4
  • 46
  • 61
  • I understand that lambdas are the preferable way to solve the problem, and I already know `std::bind` but what I need to know now, is how to use `std::function` and `std::ref` using my function `print` without using lambdas. – user7140484 Nov 13 '16 at 16:36
  • @user7140484 I can add an example with `std::function`, but `std::ref` needs `bind`/`async` or `thread` (or make_pair/tuple). And your `print` doesn't accept a reference so it doesn't make sense to use `std::ref` anyway. – krzaq Nov 13 '16 at 16:44
  • Not wanting to abuse of your patience, could you please answer my other question? http://stackoverflow.com/questions/40524697/stdbind2nd-and-stdbind-with-bidimensional-arrays-and-arrays-of-structs. Tank you in advance. – user7140484 Nov 13 '16 at 19:30
3

You do not use std::function here. It makes no sense.

std::function<...> is a type that many callable objects can be converted to. It makes sense to use this type for a variable or a function argument that should accept a callable object, especially when type erasure is desirable (e.g. when your function cannot be a template).

It does not make sense to create an std::function temporary and immediately pass it to a standard algorithm like std::for_each. Standard algorithms generally accept all kinds of callable objects, including any you could create std::function from. So std::function would be nothing but a redundant middleman.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243