
Alexander Nasonov <alnsn <at> yandex.ru> writes:
I have a proof-of-concept implementation for
BOOST_SCOPE_EXIT( (&a)(&b)(c) ) { std::cout << a << '\n' << b << '\n' << c << '\n'; } BOOST_SCOPE_EXIT_END
Hi, I managed to fix gcc ICEs and to get rid of indirect function call by following my previous code more closely. And I love the new code and the new syntax, they'll make a transition to c++0x much smoother. I have a couple of things in my TODO list but they can wait for the next release. See my commit to trunk: https://svn.boost.org/trac/boost/changeset/50620 I appreciate if people can run regression tests, especially on Windows because I don't use Windows at the moment. The sooner we get results for supported compilers/platforms the bigger is change that release managers will approve it for *this* release. Note that I missed status/Jamfile.v2. Before running regression.py, please make sure that scope_exit entry is in the file or add it manually. I'll commit as soon as I get back to home. Below you can find a human-readable expansion of the ScopeExit block quoted above. Thanks, Alex #include <boost/typeof/typeof.hpp> #if defined(__GNUC__) && !defined(__ICC) #define TPL_WORKAROUND #endif #if defined(TPL_WORKAROUND) // What are you testing, BOOST_SCOPE_EXIT or BOOST_SCOPE_EXIT_TPL? //#define TYPENAME #define TYPENAME typename #else #define TYPENAME #endif typedef void (*ref_tag)(int&); typedef void (*val_tag)(int ); template<class T, class Tag> struct member; template<class T> struct member<T,ref_tag> { T& value; #if !defined(TPL_WORKAROUND) member(T& ref) : value(ref) {} #endif }; template<class T> struct member<T,val_tag> { T value; #if !defined(TPL_WORKAROUND) member(T& val) : value(val) {} #endif }; template<class T> struct wrapper { typedef T type; }; #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() BOOST_TYPEOF_REGISTER_TEMPLATE(wrapper, 1) template<class T> wrapper<T> wrap(T&); template<class T> inline T& deref(T* p, void (*)(int&)) { return *p; } template<class T> inline T& deref(T& r, void (*)(int )) { return r; } // TODO: Change return type of deref to member<T,tag> and get rid of wrap #include <iostream> // What are you testing, BOOST_SCOPE_EXIT or BOOST_SCOPE_EXIT_TPL? //typedef int A; typedef int B; template<class A, class B> void foo(A& a, B const& b) { char c = 0; // Input: (&a)(&b)(c) typedef void (*tag_0)(int &a); typedef void (*tag_1)(int &b); typedef void (*tag_2)(int c); #if defined(BOOST_TYPEOF_NATIVE) // Note: BOOST_TYPEOF_KEYWORD should not strip const // if deref returns T const& typedef BOOST_TYPEOF_KEYWORD(deref(&a, (tag_0)0)) capture_t_0; typedef BOOST_TYPEOF_KEYWORD(deref(&b, (tag_1)0)) capture_t_1; typedef BOOST_TYPEOF_KEYWORD(deref( c, (tag_2)0)) capture_t_2; #else struct wrapped_t_0 : BOOST_TYPEOF(wrap(deref(&a, (tag_0)0))) {}; struct wrapped_t_1 : BOOST_TYPEOF(wrap(deref(&b, (tag_1)0))) {}; struct wrapped_t_2 : BOOST_TYPEOF(wrap(deref( c, (tag_2)0))) {}; typedef TYPENAME wrapped_t_0::type capture_t_0; typedef TYPENAME wrapped_t_1::type capture_t_1; typedef TYPENAME wrapped_t_2::type capture_t_2; #endif struct params_t { typedef capture_t_0 param_t_0; typedef capture_t_1 param_t_1; typedef capture_t_2 param_t_2; member<param_t_0,tag_0> param_0; member<param_t_1,tag_1> param_1; member<param_t_2,tag_2> param_2; #if !defined(TPL_WORKAROUND) params_t(param_t_0& a0, param_t_1& a1, param_t_2& a2) : param_0(a0), param_1(a1), param_2(a2) {} #endif } params #if defined(TPL_WORKAROUND) = { { deref(&a, (tag_0)0) }, { deref(&b, (tag_1)0) }, { deref( c, (tag_2)0) } }; #else ( deref(&a, (tag_0)0), deref(&b, (tag_1)0), deref( c, (tag_2)0) ); #endif void* p = ¶ms; // real code uses Watanabe's trick struct guard_t { params_t* params_; guard_t(void* p) : params_((params_t*)p) {} ~guard_t() { guard_t::body( params_->param_0.value, params_->param_1.value, params_->param_2.value ); } // TODO: don't pass c by value static void body( TYPENAME params_t::param_t_0 &a, TYPENAME params_t::param_t_1 &b, TYPENAME params_t::param_t_2 c ) { // user's code std::cout << a << '\n' << b << '\n' << c << '\n'; } } guard(p); } int main() { int i = 0; foo(i, 1u); }