Boost logo

Boost :

From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2007-03-20 12:03:50


Hello,

Section 3.2.3 of the Boost Parameter Library documentation prescribes
a remedy for lazy binding ArgumentPacks directly using the Boost
Lambda Library. I encountered some compilation errors when attempting
this. The following illustrates the problem.

$ g++ -dumpversion
4.1.2

$ cat lazy_binding_errors.cpp
#include <iostream>
#include <string>
#include <boost/lambda/lambda.hpp>
#include <boost/parameter.hpp>
using namespace boost;
using namespace boost::parameter;

BOOST_PARAMETER_NAME(s1)
BOOST_PARAMETER_NAME(s2)
BOOST_PARAMETER_NAME(s3)

template <class ArgumentPack>
std::string f(ArgumentPack const& args)
{
    std::string const& s1 = args[_s1];
    std::string const& s2 = args[_s2];
    typename binding<
        ArgumentPack, tag::s3, std::string
>::type s3 = args[_s3
                      || lambda::ret<std::string>(
                             lambda::var(s1)
                             + lambda::var(s2)
                         )
                     ];
    return s3;
}

int main()
{
    std::string x = f((_s1="hello,", _s2=" world"));
    std::cout << x << std::endl;
}

$ g++ -I./boost lazy_binding_errors.cpp 2>&1 | perl gSTLFilt.pl
...
lazy_binding_errors.cpp:24: error: no match for 'operator[]' in 'args[boost
    ::lambda::operator||(
        const boost::parameter::keyword<tag::s3> &
      , const boost::lambda::lambda_functor<
...
> &
    )
...
$

The problem is that both parameter::keyword and the lambda expression
have overloads of operator||. Since using lambda expressions in
conjunction with parameter::keywords is an intended use case for
Boost.Parameter, why not resolve the problem by providing an
operator|| specifically for this case?

template <class Tag, class Default>
aux::lazy_default<Tag, lambda::lambda_functor<Default> >
operator||(keyword<Tag> const& key,
           lambda::lambda_functor<Default> const& default_)
{
    return key.operator||(default_);
}

The attached patch implements this. Apply with 'patch -p0 <
djw_lazy_binding.patch' from the boost root directory.

However, after the patch is applied the following errors occur.

$ g++ -I./boost lazy_binding_errors.cpp 2>&1 | perl gSTLFilt.pl
...
lazy_binding_errors.cpp:24: error: conversion from 'void' to non-scalar type
    'string' requested

./boost/boost/parameter/aux_/arg_list.hpp:136: error: return-statement with a
    value, in function returning 'void'
...
$

These errors happen because lazy binding ultimately depends on
boost::result_of to deduce the type of the lambda expression, but
boost::result_of doesn't handle lambda expressions. This issue can be
resolved by applying the two patches I submitted previously.

mpl patch: http://tinyurl.com/35x5z5
utility patch: http://tinyurl.com/2h3g7n

These patches do not need to be applied in any particular order.
Applying all three has the effect of making lazy binding behave more
like the description in the documentation. I ran the Boost Parameter
Library test suite and everything passed. Let me know if I've
misunderstood something or if there's a better way to solve this
problem or if you'd like additional documentation/tests.

Thanks!
Daniel Walker




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