Perfect forwarding of slots only possible with auto&& parameter pack
djromberg opened this issue · comments
First of all: Great library, I completely switched from Boost.Signals2 to your implementation.
This could be the wrong place, however, I have problems with defining perfect forwarding slots. Given these two connection examples to a print function taking a universal reference:
#include <iostream>
#include <sigslot/signal.hpp>
void print(int&& i)
{
std::cout << std::forward<int>(i) << std::endl;
}
int main()
{
sigslot::signal<int> sig;
// does not compile: cannot bind rvalue reference of type ‘int&&’ to lvalue of type ‘int’
sig.connect([](int&& i) {
print(std::forward<int>(i));
});
// compiles and works
sig.connect([](auto&& ...i) {
print(std::forward<int>(i)...);
});
sig(42);
return 0;
}
Only the second one compiles, the other one gives me an error: cannot bind rvalue reference of type ‘int&&’ to lvalue of type ‘int’
This might be related to my compiler (gcc 8.2.1), but maybe you have a simple explanation.
Best regards
Daniel
Ok, I think I learned why this happens: It is not the variadic parameter pack, but the "auto" that will make the lambda a templated one. A template parameter T&& will match "more" due to the reference collapsing rules. Unlike int&&, T&& will collapse to either T& or T&& depending on how the function was called.
I now use this for my perfect forwarding slot:
sig.connect([&target](auto&& value) {
target.push(std::forward<decltype(value)>(value));
});
Sorry for the noise!
I am glad you find the library useful.
Yes, your