Boost logo

Boost :

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


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

$ 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;


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(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
lazy_binding_errors.cpp:24: error: no match for 'operator[]' in 'args[boost
        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
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:
utility patch:

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.

Daniel Walker

Boost list run by bdawes at, gregod at, cpdaniel at, john at