4

In C++ there are several ways to pass function as parameter, but I would like to understand whats is the vantages and advantages of each one, for example, looking the signature of functions from algorithm:

template <class RandomAccessIterator, class Compare>
  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

Why std algorithm uses template for pass function instead of std::function?

Why thread uses move semantic and algorithms functions don't?

template <class Fn, class... Args>
explicit thread (Fn&& fn, Args&&... args);

PS: I am disregarding the ways used in C as function pointers.

Captain Giraffe
  • 14,407
  • 6
  • 39
  • 67
Alex
  • 3,301
  • 4
  • 29
  • 43
  • 2
    Fyi, `std::function` post-dates `std::sort` (and indeed *all* of the "callables" in the standard library algorithms prior to C++11). – WhozCraig Apr 07 '16 at 00:41

2 Answers2

5

Why std algorithm uses template for pass function instead of std::function?

There was no std::function in C++98. One alternative is to have an abstract Comparator base class with a virtual member function to be overridden by concrete comparator classes, but the template version is more efficient since it avoids the overhead of virtual dispatch; if Compare is a class type, then the operator() can often be inlined. This would also be an argument against using std::function today.

Why thread uses move semantic and algorithms functions don't?

There also were no rvalue references in C++98.

It is easy to see that now that we have rvalue references and move semantics, it would be silly to not allow values to be moved into threads (since some types are not copyable or not efficiently copyable).

Why should std::sort take its comparator by value? See why function objects should be pass-by-value for discussion.

Community
  • 1
  • 1
Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • So today, the best way to pass function as parameter is the thread way for generic functions, and std::function to the others? – Alex Apr 07 '16 at 00:54
  • @Alex What's a "generic function"? – user253751 Apr 07 '16 at 00:56
  • A function like std::thread receives, with any number and types of argument – Alex Apr 07 '16 at 00:57
  • 5
    @Alex: You only need to use `std::function` if the type of the function can only be determined at runtime, or if it can change during runtime. If it can be determined at compile time, there is no reason to use `std::function`. – Benjamin Lindley Apr 07 '16 at 01:07
1

Why std algorithm uses template for pass function instead of std::function?

There is no need for std::function as sort, for example, directly calls your comp callable (be it a function, function call operator, etc) inside and is done with it, when it exits. When you create an instance of std::function you are storing the callable (optionally bound with some arguments).

std::thread on the other hand needs to store the Fn and the Args when it exits out of the constructor, as they are used by the newly spawned thread.

Why thread uses move semantic and algorithms functions don't?

Again, std::thread stores the data you pass to the constructor and hence the move semantics. Algorithms on the other hand just call your callable and don't need to store it.

UPDATE:

So, if you have an inline function, you can follow the sort semantics and pass the function as a template parameter.

Otherwise, use std::function. This is essentially what std::thread does -- it binds fn with args and stores it as a shared ptr.