1

Consider the following struct, which stores a function:

struct yyy {
    std::function<int()> myFunc;

    void set_func_1(std::function<int()>&& f) {
        myFunc = std::move(f);
    }

    template<typename funcT>
    void set_func_2(funcT&& f) {
        myFunc = std::move(f);
    }
};

As per this answer, I know that using a template parameter allows the compiler to optimize stuff.

But for the struct above, where I'm directly moving the function to store it, is there any benefit of using the template parameter?

rodrigocfd
  • 6,450
  • 6
  • 34
  • 68

1 Answers1

3

&& references, even though spelled the same way, play different roles.

void set_func_1(std::function<int()>&& f) {
    myFunc = std::move(f);
}

is correct but only takes r-value references. In template<typename funcT> void set_func_2(funcT&& f), && is a forwarding reference, so using std::move(f) in the body is wrong - it could steal state from a non-temporary object. Instead, you would need to use std::forward<funcT>(f).

An advantage of the 2nd function compared to the 1st is not optimization. The first one is only going to accept r-values, so e.g. function<int> f = []{return 1;}; struct yyy; yyy.set_func_2(f); will not compile.

A good, simple, near-optimal way for writing set() methods is passing by value and moving:

    void set_func_3(std::function<int()> f) {
    myFunc = std::move(f);
}

"Modern effective C++" book by Scott Meyers has more details on its applicability.

Eugene
  • 6,194
  • 1
  • 20
  • 31
  • Thanks for the near-optimal example. What would be the optimal one? – rodrigocfd Sep 19 '19 at 09:53
  • The corrected template version is the optimal solution from performance perspective. But extra complications caused by the template are usually more important than the tiny improvement. – Eugene Sep 19 '19 at 11:10
  • So the optimal solution is the template without the `&&`? – rodrigocfd Sep 19 '19 at 11:24
  • 1
    The optimal is the template with `&&` and with `std::forward<..>`. But I would not use it unless this is a proven performance bottleneck. – Eugene Sep 19 '19 at 13:44