Boost logo

Boost :

From: Atry (pop.atry_at_[hidden])
Date: 2007-06-26 12:51:46


Alexander Nasonov wrote:
> I couldn't find out quickly if you're applying BOOST_TYPEOF to passed lambda expression but if you do, it would blow up your computer if compiler doesn't support native typeof (Hint: try passing -DBOOST_TYPEOF_COMPLIANT to compiler's arguments).
>
> Have you considered something like
>
> int (*static_fun)(int const&, int const&) = (_1 + _2 + 3).get_static_function(1, 2);
>
> get_static_function does not necessarily accept values, it may have a different interface:
> (_1 + _2 + 3).get_static_function<int const&, int const&>();
> (_1 + _2 + 3).get_static_function(mpl::vector<int const&, int const&>());
>
> Does your idea help to improve performance and/or reduce size of program that has a lot of conversions from lambda expressions to tr1::function?
>
> 26.06.07, 17:31, Atry <pop.atry_at_[hidden]>:
>
>
>> I wrote a intial version, I have tested it on cygwin ported gcc 3.4.4 and
>> msvc 7.1, for more infomation, see README and tests in zip packet in vault.
>> http://boost-consulting.com/vault/index.php?direction=0&order=&directory=Generic%20Programming
>> On 6/25/07, Atry <pop.atry_at_[hidden]> wrote:
>>
>
>
Yes, getting a static function pointer is easy, I will add that method
later. But I have highly depended on typeof, I use typeof to determine
the result of almost all expressions, and Boost.Lambda does not. Typeof
enhanced lots of flexibility. For example, if a operator is overrided to
return a unusual return value, for Boost.Lambda, you have to manually
specify that return value using a "ret<return_type>(expr)" syntax. And I
used typeof to avoid that.

There is two situation need static lambda.
a. To generate a short c function pointer.
b. To generate a short generic function, and pass it to a template class.

For example, I have some "component" class, and each of them depend on
some others. How could they find each other? one way is pass a pointer.
/* code begin */
class component_a
{
public:
  void foo();
};

class component_b
{
private:
  component_a* a_;
public:
  component_b(component_a* a) : a_(a) {}
  void bar()
  {
    foo();
  }
};

class global_object
{
public:
  component_a a_;
  component_b b_;
  global_object() : a_(), b_(&a_)
  {
    b_.bar();
  }
};
int main()
{
  global_object g;
}
/* code end */
As you see, there is a component_a and a component_b. Component_b
depends on component_a, and global_object combine these two. But it is
not flexible enough. Firstly, component_b used a fixed type of
component_a, we can't have another implement of component_a. Secondly,
the pointer to component_a in component_b is unwanted, there is some way
to avoid that pointer. Look at the improved version using static lambda:
/* code begin */
#include <boost/assert.hpp>
#include <boost/static_lambda.hpp>
#include <cstddef>
class component_a
{
public:
  int foo()
  {
    return 1;
  }
};

template<typename Locator_A>
class component_b
{
public:
  void bar()
  {
    BOOST_ASSERT(Locator_A::static_invoke(this)->foo() == 1);
  }
};

struct locator_to_a;
class global_object
{
public:
  component_a a_;
  component_b<locator_to_a> b_;
  global_object() : a_(), b_()
  {
    b_.bar();
  }
};

// declare constant "offset_of_a".
BOOST_STATIC_LAMBDA_AUTO_EXPRESSION(offset_of_a, offsetof(global_object,
a_));

// declare constant "offset_of_b".
BOOST_STATIC_LAMBDA_AUTO_EXPRESSION(offset_of_b, offsetof(global_object,
b_));

using namespace boost::static_lambda;

// the static lambda function. note: constructing a pointer equals to
casting to a pointer.
typedef BOOST_STATIC_LAMBDA_FUNCTOR
(
  construct<component_a*>
  (
    construct<char*>(_1) - offset_of_b + offset_of_a
  )
) l;
struct locator_to_a : l{};
int main()
{
  global_object g;
}

/* code end */


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