3
#include <iostream>
#include <functional>

using Callback = std::function<void(const int)>;

int main() {
    Callback testCall = [](const int &num) {
        std::cout << "callback: " << num << " - " << &num << std::endl;
    };
    int num = 42;
    testCall(num);
    std::cout << "main:     " << num << " - " << &num << std::endl;
}

Possible output:

callback: 42 - 000000B19197F618
main:     42 - 000000B19197F694

As you can see, even if i assign a lambda function which takes the parameter by reference it still uses a copy.

Is that correct?

If yes, why does it still compile? Why is there at least not a warning about the discrepancy between the Callback declaration parameters and the assigned lambda. (const int &num vs const int num)

When not usingconst it does not compile.

PS. if you find a better title, feel free to edit.

Iceflower S
  • 144
  • 3
  • 18
  • 3
    is this discrepancy `int` on `Callback` and `const int&` on the lambda on purpose? If yes you should mention that in the question. When I first read it i overlooked that detail – 463035818_is_not_an_ai Mar 12 '20 at 09:40
  • @idclev463035818 thats exactly what the question is about – Iceflower S Mar 12 '20 at 09:41
  • 1
    The std function takes a non reference argument parameter Use ` std::function` instead, it will work – Antoine Morrier Mar 12 '20 at 09:44
  • ok, then maybe make it more clear in the question. I was reading it in detail and completely missed the type of the callback – 463035818_is_not_an_ai Mar 12 '20 at 09:45
  • 2
    also, making it more clear in the question will avoid comments that tell you to fix the type of the callback ;) As I understood you are asking whether this is correct behavior (not how to fix the code) – 463035818_is_not_an_ai Mar 12 '20 at 09:46
  • 2
    You could replace `std::function` with `std::function` and it would still compile. `std::function` is a class used for type-erasure, so as long as calling one signature with another would make sense and is legal it will work. – super Mar 12 '20 at 10:05

1 Answers1

2

This is because testCall is a functor object that catch its parameter by copy and then call the lambda on it.

Try:

Callback f = [](const int &num) {
        std::cout << "callback: " << num << " - " << &num << std::endl;
};

int main() {
        int num = 999;
        std::cout << "callback: " << num << " - " << &num << std::endl;
        f(num);
        [](const int &num) {
                std::cout << "callback: " << num << " - " << &num << std::endl;
        }(num);
}

you will see something like:

callback: 999 - 0x7ffeed60a9bc
callback: 999 - 0x7ffeed60a994
callback: 999 - 0x7ffeed60a9bc    

which means that callBack is not the function by itself but an indirection to the function. And there is no problem regarding types...

Answer to this may helps you to understand what happens under the hood: How std::function works

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69