Boost logo

Boost :

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


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