C++Guns – RoboBlog

07.01.2019

C++ Guns: Pass function objects per Forwarding references!

Filed under: Allgemein — Tags: — Thomas @ 19:01

I say: Pass (template) function objects per Forwarding references! and not per value. The reason is simple: it works also with function objects with state.

https://en.cppreference.com/w/cpp/language/reference

A little example will show it:

#include <iostream>
#include <random>
using namespace std;

template<typename Function>
auto perValue(Function f) {
  return f();
}

template<typename Function>
auto perForwardReference(Function&& f) {
  return f();
}

int main() {
  std::minstd_rand gen(1156823295);
  
  cout << "Generate 5 random numbers:\n";
  cout << "calls to perValue:\n";
  for(int i=0; i < 5; i++) {
    cout << perValue(gen) << "\n";
  }
  
  cout << "calls to perForwardReference:\n";
  for(int i=0; i < 5; i++) {
    cout << perForwardReference(gen) << "\n";
  }  
}

Generate 5 random numbers:
calls to perValue:
4
4
4
4
4
calls to perForwardReference:
4
193084
730423176
870612250
1216431607

It doesn’t work because the random number generate object has a state. The call to function perValue() change this state on a copy of the generator. And not the one, we pass as argument. But there is no compile time error. Not a single warning. That's the worst case IMO.

The C++ standard and Scott Meyers book "Effective STL" recommend to pass by value. IMO for historical reasons.

C++11 §25.1/10:
[ Note: Unless otherwise specified, algorithms that take function objects as arguments are permitted to copy those function objects freely. Programmers for whom object identity is important should consider using a wrapper class that points to a noncopied implementation object such as reference_wrapper (20.8.3), or some equivalent solution. —end note ]

stackoverflow: why function objects should be pass-by-value

The standard should be updated and the book is horrible outdated. It was written 2008 and forward references come with C++2011. The old solution is to wrap the function into something which can be pass by value, but also change the state. We have now (2011) std::function for that task. And not this ugly thing in the book.

No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress