-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update Delegate
and Signal
for lambdas
#1015
Comments
One area of concern I wanted to mention regarding the use of First off, the performance comparison was relating Second, the potential use of external memory is because According to the C++ standard, the
Notably absent is a pointer to a member function. This is relevant, as all our current uses are pretty similar to calling Example: #include <iostream>
#include <functional>
struct Object{
void method() {}
};
int main() {
Object object;
const auto func1 = std::bind(&Object::method, &object);
const auto func2 = [&object]{ object.method(); };
std::cout << sizeof(func1) << std::endl; // 24 - (64-bit g++)
std::cout << sizeof(func2) << std::endl; // 8 - (64-bit g++)
std::function<void()> callback;
callback = func1; // external allocation
callback = func2; // no external allocation
} The reason for the difference in size is the lambda stores only a single pointer to As for verifying the lambda can be stored without extra memory allocation, that can be done with In summary, |
On a related matter, there is a proposal for a non-owning It may be worth giving some consideration to ownership characteristics. Should Currently On the other hand, Somewhat complicating the matter is that all When the delegate is a callback to a long lived object, extra storage can be kept in that long lived object, rather than the delegate. Such a setup makes For more local usage, such as for an immediate callback, catpure group parameters could potentially be stored in a auto data = std::tuple(a, b, c);
auto func = [&data]() { doSomething(data); };
someFunctionCallWithACallback(func); This seems to be more what someFunctionCallWithACallback([&a, &b, &c]() { doSomething(a, b, c); }); This isn't really our use case though. I think we should probably stick with A deeper question is if we even need the |
I spent a fair bit of time doing research into Basic research:
Andrzej's C++ blog: The Old New Thing: Arthur O'Dwyer's blog: Misc related research:
Standard library documentation: Standard library implementations and proposals: |
So I've discovered a bit of a snag. There is no There is a Conceptually it should be fairly simple to compare a lambda instance if you know they're the same type, and all captures are equality comparable. It would essentially be the same as the default equality comparison for any regular |
Bit of a side note, but I've always found the Edit: Found this:
So it looks like it's a workaround for VC6. That's pretty old, and rather irrelevant at this point. Edit: Found a lot of comments describing why things are they way they are were removed back in: |
Our
Delegate
code is super old. We should consider updating it.The
Delegate
code has a lot of macro#if
to support really old compilers. Our code relies on C++17, and perhaps soon, C++20. That means we need a reasonably modern compiler. We could gut many of the#if
checks for old compiler support from theDelegate
code.Our custom
Delegate
implementation is from about 2005. Source:https://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates
The current implementation far predates the C++11 standard, which introduced
std::function
. It seemsstd::function
replaces the need to write a customDelegate
class. Maybe we should update to usingstd::function
and get rid of the customDelegate
class.Our current implementation of
Delegate
andSignal
only really supports member function pointers. We should add lambda support when callingSignal::connect
andSignal::disconnect
.It may be possible to inline the lambda. Here's how lambdas would compare to the existing way:
signal.connect([&object]() { object.method(); }); signal.connect(&object, &object::method);
If we move to
std::function
, it may make sense to use lambdas as the primary means of representingDelegate
. That might mean using it as the primary storage type internally, or perhaps updating calls to prefer passing lambdas.The text was updated successfully, but these errors were encountered: