Boost logo

Boost :

From: Michael Goldshteyn (mgoldshteyn_at_[hidden])
Date: 2006-07-25 11:33:27


I have an interesting dilemma in my usage of boost::bind. Consider:

---
// Definitions
class Key;
class BigValue
{
public:
    const Key &GetKey() const;
};
class MyMap
{
public:
  void Insert(const Key &k, const BigValue &v);
};
// Usage
void foo()
{
    std::vector<BigValue> lotsOfValues;
    // Populate lots of values...
    ...
    // Transfer those values to the map, using the keys which are within the 
values
    MyMap myMap;
    // The transfer and also, the dilemma
    // Solution 1
    std::for_each(
        lotsOfValues.begin(),
        lotsOfValues.end(),
        boost::bind(
            MyMap::Insert, // The function used to insert
            boost::ref(myMap), // The map into which we are inserting the 
keys/values
            boost::bind(BigValue::GetKey,_1), // The function to be called 
to extract the key from the value
            _1
        )
    );
}
---
OK, this compiles and works, but the fourth parameter to the outer bind, _1, 
must be copied each time an Insert takes place, from my understanding of how 
bind works. Since this is a "BigValue" and the Insert() function in MyMap 
takes a const reference as it's second parameter, I would like for it not to 
be copied. So, the solution becomes:
// Solution 2
---
    std::for_each(
        lotsOfValues.begin(),
        lotsOfValues.end(),
        boost::bind(
            MyMap::Insert, // The function used to insert
            boost::ref(myMap), // The map into which we are inserting the 
keys/values
            boost::bind(BigValue::GetKey,_1), // The function to be called 
to extract the key from the value
            boost::bind<const BigValue &>(boost::cref<BigValue>,_1) // Get 
at the value, without creating a temporary BigValue
        )
    );
---
Well this sure looks overly complex. Shortcuts, such as the following, will 
not compile:
// Invalid solution 3
---
    std::for_each(
        lotsOfValues.begin(),
        lotsOfValues.end(),
        boost::bind(
            MyMap::Insert, // The function used to insert
            boost::ref(myMap), // The map into which we are inserting the 
keys/values
            boost::bind(BigValue::GetKey,_1), // The function to be called 
to extract the key from the value
            boost::cref(_1) // Attempt to use the cref directly, and let 
bind deduce the type (fails to compile)
        )
    );
---
// Invalid solution 4
---
    std::for_each(
        lotsOfValues.begin(),
        lotsOfValues.end(),
        boost::bind(
            MyMap::Insert, // The function used to insert
            boost::ref(myMap), // The map into which we are inserting the 
keys/values
            boost::bind(BigValue::GetKey,_1), // The function to be called 
to extract the key from the value
            boost::bind(boost::cref<BigValue>,_1) // Attempt to use the 
cref, deferred, and let bind figure out the resultant return type (fails to 
compile)
        )
    );
---
Is there a simpler solution than Solution 2, above?
Thanks,
Michael Goldshteyn

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