1

I have a map which is being iterated over in a std::for_each loop. I am using a nested bind and simple helper functions to get to the element of the pair I require. This has to be usable from pre c++11 code.

typedef std::map<int, Foo> MapType;

std::for_each( 
    testMap.begin() , 
    testMap.end() , 
    std::bind( 
      &Foo::myIncredibleFunction ,  
      std::bind( 
          &ValueExtractor< MapType::key_type , MapType::mapped_type >::getValue, 
          std::placeholders::_1 )));

This works fine (although I'm sure could be refined)

I am also going to be migrating the current code base from the current level to C++11 and so I am looking at whether I can use new features of the language to improve the code (readability, efficiency). For example I have tried the following (Unsuccessfully - see template error below)

std::for_each( 
    testMap.begin() , 
    testMap.end() , 
    std::bind( 
        &Foo::myIncredibleFunction ,  
        std::get<1>(  std::placeholders::_1 )));

error

    1>d:\projects\test_bind\test_bind\test_bind.cpp(48): error C2780:
    std::bind ...<Snip>...
    : expects 6 arguments - 2 provided

also intellisense has the following:

IntelliSense: no instance of overloaded function "std::get" matches the argument list
argument types are: (std::_Ph<1>)   

I have tried various combinations of usages of std:get<1>() to try to replace my inner bind with no success. I suspect that I am failing to understand this properly but it feels like I should be able to do what I want. Is there a way to do this using the std::get call and without a helper function/functor?

Edit: I think KennyTM has come up with my answer with regard to what I actually do in the code, it's so much better than my approach. I'm still interested in whether std::get<> could be used above or why not.

4

2 回答 2

4

Since you're using C++11 already, why not use a range-based for loop (which is supported in VS 2012)?

for (auto&& item : testMap) {
    item.second.myIncredibleFunction();
}
于 2013-06-20T08:32:33.890 回答
3

Your problem is that std::get<1>(_1) is a perfectly fine function invocation on its own.

What you want to do here is called function composition, which can be done with nested bind calls, e.g. std::bind(foo, std::bind(bar, _1)). The problem here is the second part, where bar = std::get<1> - std::bind(&std::get<1>, _1) would be the obvious first try, but that doesn't work because std::get takes more template parameters.

One solution is a custom function object:

#include <utility>

template<unsigned I>
struct get{
  template<class T>
  auto operator()(T&& v) -> decltype(std::get<I>(std::forward<T>(v)))
  { return std::get<I>(std::forward<T>(v)); }
};

And then: std::bind(&Foo::myIncredibleFunction, std::bind(get<1>(), _1)).

于 2013-06-20T08:54:54.997 回答