Hello all,
Can anyone try the following code on a MSVC compiler with lambdas (MSVC10?)? #include <vector> struct person {}; struct world { void add_person(person const& a_person) { bool commit = false; persons_.push_back(a_person); auto scope_exit = [&commit, &persons_]() mutable -> void { if(!commit) persons_.pop_back(); }; commit = true; scope_exit(); } private: std::vector<person> persons_; }; int main() { world w; person p; w.add_person(p); return 0; } This code compiles on GCC 4.5.3 with C++0x extensions (including lambdas) but based on some errors I'm seeing in trunk's ScopeExit regressions tests, I'm guessing it will fail using MSVC lambdas with errors similar to the followings: error C3480: 'world::persons_': a lambda capture variable must be from an enclosing function scope warning C4573: the usage of 'world::persons_' requires the compiler to capture 'this' but the current default capture mode does not allow it Unfortunately, I don't have a MSVC compiler with lambdas so thank you very much for trying my code! --Lorenzo |
GCC 4.5 is in error to allow that. 4.7 does not allow it. The correct way to use a data member in the lambda is to capture "this", and then access the member via "this->member" inside the lambda. Regards, Nate _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
OK, thanks. This is a problem for implementing ScopeExit using lambdas on C++11 because the following code: struct world { void add_person(person const& a_person) { bool commit = false; persons_.push_back(a_person); SCOPE_EXIT( (&commit) (&persons_) ) { if(!commit) persons_.pop_back(); } commit = true; } private: std::vector<person> persons_; }; Works with the current implementation of ScopeExit that does not use lambdas but it will no longer compile with the implementation of ScopeExit that uses lambdas. Therefore, the lambda implementation of ScopeExit cannot be backward compatible... I will discuss this issue with ScopeExit's main author Alexander Nasonov but this might mean that ScopeExit will never be implemented internally using lambdas, not even on C++11 compilers. Thanks. --Lorenzo |
In reply to this post by Nathan Ridge
on Wed Mar 14 2012, Nathan Ridge <zeratul976-AT-hotmail.com> wrote: > GCC 4.5 is in error to allow that. 4.7 does not allow it. > > The correct way to use a data member in the lambda is to capture "this", and then > access the member via "this->member" inside the lambda. Actually you get implicit access to all the members once you capture "this." That said, I don't think anyone should use that capability :-) -- Dave Abrahams BoostPro Computing http://www.boostpro.com _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
In reply to this post by lcaminiti
lcaminiti wrote:
> > Nathan Ridge wrote > > > > GCC 4.5 is in error to allow that. 4.7 does not allow it. > > > > The correct way to use a data member in the lambda is to capture "this", > > and then > > access the member via "this->member" inside the lambda. > > If the above it true ... > Works with the current implementation of ScopeExit that does not use lambdas > but it will no longer compile with the implementation of ScopeExit that uses > lambdas. Therefore, the lambda implementation of ScopeExit cannot be > backward compatible... I will discuss this issue with ScopeExit's main > author Alexander Nasonov but this might mean that ScopeExit will never be > implemented internally using lambdas, not even on C++11 compilers. then don't claim backward-compatibility and make sure that lambda implementation can't be implicitly enabled (only if a user defines BOOST_SCOPE_EXIT_USE_LAMBDAS or something like this). Alex _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
1) I'd propose to never implement BOOST_SCOPE_EXIT using lambdas. There is no advantage for the user in the lambda implementation because I already extended BOOST_SCOPE_EXIT to use variadic macros, capture the object `this_`, and capture no variable (using `void`) all of which without using C++11 and maintaining backward compatibility with the existing BOOST_SCOPE_EXIT syntax. // On all compilers (it never uses C++11 lambdas). BOOST_SCOPE_EXIT(&commit, &persons_) { if(!commit) persons_.pop_back(); } BOOST_SCOPE_EXIT_END 2) However, I'd leave BOOST_SCOPE_EXIT_ALL because it allows for implicit captures using `&` and `=`. This macro uses C++11 lambdas and it is #defined only for C++11 compilers. BOOST_SCOPE_EXIT_ALL and BOOST_SCOPE_EXIT will therefore have different capture semantics (e.g., BOOST_SCOPE_EXIT_ALL cannot capture data members without capturing `this` while BOOST_SCOPE_EXIT can) but if users find that confusing they just don't use SCOPE_EXIT_ALL. // Only on C++11 compilers (same capture semantics of C++11 lambda and therefore different from BOOST_SCOPE_EXIT). BOOST_SCOPE_EXIT_ALL(&, this) { if(!commit) persons_.pop_back(); }; // Use `;` instead of BOOST_SCOPE_EXIT_END 3) Finally, if you #define BOOST_SCOPE_EXIT_CONFIG_NO_CXX11 (or shall this be NO_CPP11? ;) ) then BOOST_SCOPE_EXIT_ALL is never defined not even on C++11 compilers. This way the user is always in control and he/she gets the extra benefits of implicit lambda captures when they apply. What do you think? Thanks. --Lorenzo |
lcaminiti wrote:
> 1) I'd propose to never implement BOOST_SCOPE_EXIT using lambdas. There is > no advantage for the user in the lambda implementation because I already > extended BOOST_SCOPE_EXIT to use variadic macros, capture the object > `this_`, and capture no variable (using `void`) all of which without using > C++11 and maintaining backward compatibility with the existing > BOOST_SCOPE_EXIT syntax. If we assume that the new standard is immutable, then you reasoning makes perfect sense. However, what if it was an oversight by the standard committee? 'this' is not a local variable, after all. If they allowed a special case for this, they could also allow data members. Alex _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
In reply to this post by lcaminiti
On 15/03/12 20:21, lcaminiti wrote:
> 1) I'd propose to never implement BOOST_SCOPE_EXIT using lambdas. There is > no advantage for the user in the lambda implementation What about 1) compile-time speed 2) run-time efficiency Aren't both of those better with lambdas? _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
In reply to this post by Alexander Nasonov
On 16/03/12 03:42, Alexander Nasonov wrote:
> If we assume that the new standard is immutable, then you reasoning > makes perfect sense. However, what if it was an oversight by the > standard committee? 'this' is not a local variable, after all. If they > allowed a special case for this, they could also allow data members. It is not an oversight, and is this way on purpose. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
on Fri Mar 16 2012, Mathias Gaunard <mathias.gaunard-AT-ens-lyon.org> wrote: > On 16/03/12 03:42, Alexander Nasonov wrote: > >> If we assume that the new standard is immutable, then you reasoning >> makes perfect sense. However, what if it was an oversight by the >> standard committee? 'this' is not a local variable, after all. If they >> allowed a special case for this, they could also allow data members. > > It is not an oversight, and is this way on purpose. That may be, but it is considered a mistake by at least a few of us on the commitee, and we've discussed ways to rectify it. -- Dave Abrahams BoostPro Computing http://www.boostpro.com _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
In reply to this post by Mathias Gaunard-2
Bases on my LocalFunction benchmarking: https://svn.boost.org/svn/boost/trunk/libs/local_function/doc/html/boost_localfunction/Alternatives.html I'd expect ScopeExit with lambdas to be only marginally if at all faster than ScopeExit without lambas for both compile and run time. But I must confess that I didn't directly benchmark ScopeExit with and without lambdas so I could be mistaken. --Lorenzo |
In reply to this post by Dave Abrahams
Does anyone know what was the rationale of the committee for this? Then, as Alex suggested, I will leave the BOOST_SCOPE_EXIT implementation that uses lambdas however it will be disabled by default, enabled only if users explicitly #define BOOST_SCOPE_EXIT_CONFIG_USE_CXX11_LAMBDAS, and I will document that BOOST_SCOPE_EXIT with lambdas is not backward compatible (unless C++11 is rectified to allow lambdas to capture data members). Thanks a lot. --Lorenzo |
In reply to this post by lcaminiti
On 16/03/12 20:50, lcaminiti wrote:
> > Mathias Gaunard-2 wrote >> >> On 15/03/12 20:21, lcaminiti wrote: >> >>> 1) I'd propose to never implement BOOST_SCOPE_EXIT using lambdas. There >>> is >>> no advantage for the user in the lambda implementation >> >> What about >> 1) compile-time speed >> 2) run-time efficiency >> >> Aren't both of those better with lambdas? >> > > Bases on my LocalFunction benchmarking: > https://svn.boost.org/svn/boost/trunk/libs/local_function/doc/html/boost_localfunction/Alternatives.html > > I'd expect ScopeExit with lambdas to be only marginally if at all faster > than ScopeExit without lambas for both compile and run time. But I must > confess that I didn't directly benchmark ScopeExit with and without lambdas > so I could be mistaken. Doesn't the use of C++11 remove all the ugly virtual stuff? _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
In reply to this post by lcaminiti
On 16/03/12 20:55, lcaminiti wrote:
> Then, as Alex suggested, I will leave the BOOST_SCOPE_EXIT implementation > that uses lambdas however it will be disabled by default, enabled only if > users explicitly #define BOOST_SCOPE_EXIT_CONFIG_USE_CXX11_LAMBDAS, and I > will document that BOOST_SCOPE_EXIT with lambdas is not backward compatible > (unless C++11 is rectified to allow lambdas to capture data members). Or you could change your library to explicitly require to bind member variables or this, like C++11 does. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
In reply to this post by Mathias Gaunard-2
No, the "virtual stuff" is used by LocalFuncttion* to pass local classes as template parameters but it is not required at all by ScopeExit. (*) Note: A static member function and a static_cast were used at the end instead of the "virtual stuff" because faster. On C++11, neither of this trick is needed because local classes can be passed as template parameters but not because of lambdas which are not used by LocalFunction. Thanks, --Lorenzo |
In reply to this post by Mathias Gaunard-2
But if I require ScopeExit to explicitly bind member variables or this like C++11 lambdas do, that breaks backward compatibility with code that use the current implementation of ScopeExit :( For example the following code that compiles with the current version of ScopeExit will no longer compile: struct x { int y; void f() { BOOST_SCOPE_EXIT( (&y) ) { y = -1; } BOOST_SCOPE_EXIT_END } }; --Lorenzo |
Free forum by Nabble | Edit this page |