I have the following code (using boost 1.55 on MSVC9):
struct pair_first_impl
{
template<class TPair> struct result { typedef typename TPair::first_type type; };
template<class TPair>
typename TPair::first_type const& operator() (TPair const& pair) const
{
return pair.first;
}
template<class TPair>
typename TPair::first_type& operator() (TPair& pair)
{
return pair.first;
}
};
static phx::function<pair_first_impl> pair_first;
int test()
{
std::map<int, std::string> mymap;
std::find_if(mymap.begin(), mymap.end(), pair_first(_1) == 1);
}
I'm getting a compiler error regarding pair_first_impl::result::type
, which says:
error C2825: 'TPair': must be a class or namespace when followed by '::'
see reference to class template instantiation 'pair_first_impl::result<TPair>' being compiled
with
[
TPair=const pair_first_impl (std::pair<const int,std::string> )
]
For some reason, it looks like it is passing in a function type (?) into my TPair
template argument instead of the std::pair
type directly.
Can anyone help me figure out what I'm doing wrong here?
I found the solution by reviewing the result_of protocol documentation (which is separate from phoenix; I was expecting phoenix docs to explain):
struct pair_first_impl
{
template<class> struct result;
template<class F, class TPair>
struct result<F(TPair)>
{
typedef typename boost::remove_reference<TPair>::type actual_type;
typedef typename actual_type::first_type type;
};
template<class TPair>
typename TPair::first_type const& operator() (TPair const& pair) const
{
return pair.first;
}
template<class TPair>
typename TPair::first_type& operator() (TPair& pair)
{
return pair.first;
}
};
static phx::function<pair_first_impl> pair_first;
int test()
{
std::map<int, std::string> mymap;
std::find_if(mymap.begin(), mymap.end(), pair_first(_1) == 1);
return 0;
}
The problem was that I thought that the type passed into the template parameter for the nested result
struct was the type of the first parameter, which it isn't. It's actually the whole function type. So a template specialization of result
must be created the can be used to extract the type of the first argument. You can then use this to access first_type
in the pair.
My _1
placeholder is valid because at the top of my source file I'm doing the following:
using namespace boost::phoenix::placeholders;
namespace phx = boost::phoenix;