$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: [boost] tiny lambda snippet that fails to compile with boost 1.46
From: Mark Van Dijk (Mark.VanDijk_at_[hidden])
Date: 2011-02-24 19:30:38
I have a question about a particular problem I'm having with boost::lambda.   I've distilled it down to a tiny complete app (shown below).
The complier is complaining about bl::_1 is a const std::string, but &Map::value_type::second is a member_data_pointer to a non-const string.  This line compiles with boost 1.42, but not in 1.46 (using MSVC 2008).  I have two questions:
1) is the line of code in question actually valid?  I.e. is this a boost::lambda bug or is this my bug?
2) If it is my bug, then to fix the code I need to coerce [&Map::value_type::second] to a CONST - problem is that the only way I can figure out is to use an ugly const_cast<>.  Is there a cleaner way to do this?
Source code follows:
------------------------------------------------------------------------------------------------------------
#include <iostream>
#include <string>
#include <map>
#include <cassert>
#include <boost/assign.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
namespace bl = boost::lambda;
int main()
{
    // create two simple maps and populate them
    typedef std::map<long, std::string> Map;
    Map m = boost::assign::map_list_of(0, "hello ")(1, "world!");           // non-const map
    Map const cm = boost::assign::map_list_of(0, "hello ")(1, "world!");    // const map
    // this works:
    // concatenate the std::string parts of the non-const map and send to std::cout
    //
    std::string output;
    std::for_each(
        m.begin(), 
        m.end(),
        output += bl::bind(&Map::value_type::second, bl::_1));
    std::cout << output << std::endl;
    assert(output == "hello world!");
    // works with boost 1.42, however it fails to compile with boost 1.46
    // concatenate the std::string parts of the const map and send to std::cout
    //
    output.clear();
    std::for_each(
        cm.begin(), 
        cm.end(),
        output += bl::bind(&Map::value_type::second, bl::_1));	//   <---- COMPILER ERROR HERE WITH BOOST 1.46
    std::cout << output << std::endl;
    assert(output == "hello world!");
    // this compiles, but uses an ugly const_cast<>
    // concatenate the std::string parts of the const map and send to std::cout
    //
    output.clear();
    std::for_each(
        cm.begin(), 
        cm.end(),
        output += bl::bind(const_cast<std::string const Map::value_type::*>(&Map::value_type::second), bl::_1));	//   <---- UGLY
    std::cout << output << std::endl;
    assert(output == "hello world!");
    return 0;
}