Boost logo

Boost :

Subject: Re: [boost] [scope_exit] capture list syntax for scope_exit and local_function
From: Alexander Nasonov (alnsn_at_[hidden])
Date: 2009-01-16 07:03:50


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 = &params; // 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);
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk