Avoid implicit capture of this?

Viewed 331

Is it possible to write a type such that it can't implicit capture itself this with a lambda inside itself:

[&]{}

I currently have a situation where a temporary object is used as a factory to create another object. Inside this a lot of lambda's exist - it would be great to avoid capturing data members by mistake.

(note that this is also about future proofing the code a bit as this can result in some very hard to find bugs - another programmer can come along and not realize this quite easily)

(also note, it would actually be great to capture everything with [&] in this case as I actually do want to capture everything else by reference as this binds correctly to all the new stuff being created by the factory - [=] would be incorrect.)

2 Answers

I don't really see a way to either forbid capturing this or detect it in the language (I don't really see a type trait for this, even with more creative use). Maybe there is tooling for this, but I haven't found anything. I think you have to overthink your design in some way:

  • Do not capture with [&]. Capturing all by reference is nice for local lambdas that never leave the scope, but personally, I would never use it for any lambda that is returned from the function.
  • Delegate lambda construction to a non-member function (but this is only "Do not use [&]" with extra steps)
  • If you do not want to capture this, why is the factory even an object? I do not really see, where you would use that then. Refactor the whole thing to use a static member function or even a free function (C++ ain't Java, namespaces with free functions are a great thing).
  • Not so robust, but somewhat working: Use a very recognizable naming scheme for the factory member variables (i.e. F_*), then you will recognize immediately if you are using one.

(Personally, I prefer the third point. In my opinion, classes are overused for such stuff)

EDIT: Seems like there was a pull request to llvm that adds a warning for this (or at least for captured local variables, I am unsure how that resolves with member variables). The change was seen positively but got lost on track, so it seems like someone just needs to rebase and review it to make it current. https://reviews.llvm.org/D24639

If it is important, you ought to explicitly write each variable you capture by reference/copy instead of just spamming [&] for all lambda captures.

What if they used a variable in the lambda and then used the lambda after the variable got destroyed? Isn't it the same issue as capturing this with usage of member variables? You just need to be very careful when capturing variables if you intend to forward the lambda elsewhere and stop with the bad practice of capturing everything without thinking.

Note: If you don't use any member variable then this isn't captured via [&].

Related