Reputation: 1
I was wondering if someone could help me with this issue. I have been reading that the are some problems with the use of the std::make_pair in VS2010 because it is overloaded, and I have found some workarounds that would work, however, I just can not find a way to make it work here for me.
Here is a part of the code so you can take a look:
namespace tree {
#define container std::vector
typedef container<IConnType const*> node_data;
///tree node's brief
struct tree_node
{
STD_STRING name;
node_data types;
};
struct branch;
typedef container<branch> sub_tree;
///branch's brief
struct branch
{
tree_node node;
sub_tree tree;
};
}
template<typename T>
///address of's brief
struct address_of
{
T* operator()(T& x) const
{
return &x;
}
T const* operator()(T const& x) const
{
return &x;
}
};
typedef std::pair<tree::branch*,HTREEITEM> step_info;
std::vector<step_info> steps;
/// after we fill steps ///
HTREEITEM new_item = m_conntree.InsertItem(&tvi); // m_conntree is a CTreeCtrl; tvi is a TVINSERTSTRUCT
std::transform(step.first->tree.begin()
, step.first->tree.end()
, std::back_inserter(steps)
, boost::bind(&std::make_pair<tree::branch*,HTREEITEM>
, boost::bind<tree::branch*>(address_of<tree::branch>()
, _1
)
, new_item
)
);
The problem is here (the rest of the code is just to give an idea):
std::transform(step.first->tree.begin()
, step.first->tree.end()
, std::back_inserter(steps)
, boost::bind(&std::make_pair<tree::branch*,HTREEITEM>
, boost::bind<tree::branch*>(address_of<tree::branch>()
, _1
)
, new_item
)
);
I tried to do a cast (as I had read in other thread) but it did not work... this is what I had tried:
typedef std::pair<tree::branch*,HTREEITEM> (*MakePairType)(tree::branch*,HTREEITEM);
std::transform(step.first->tree.begin()
, step.first->tree.end()
, std::back_inserter(steps)
, boost::bind((MakePairType)&std::make_pair<tree::branch*,HTREEITEM>
, boost::bind<tree::branch*>(address_of<tree::branch>()
, _1
)
, new_item
)
);
I hope anyone can help me with this one... I have been stuck for a long time trying to compile this project...
By the way, it throws me a lot of error in the boost::bind (more than a hundred)... and taking out the boost::bind, it gives me errors about not knowing which overload of std::make_pair to use,
Regards, and thanks in advance!
Upvotes: 0
Views: 642
Reputation: 355079
Dave S is right: a lambda or a functor would be far better here. The problem you are running into with make_pair
is likely due to a breaking change in C++11. make_pair
now has parameters of type T&&
and U&&
, to enable perfect forwarding of the pair type.
You're using make_pair
like so:
std::make_pair<tree::branch*,HTREEITEM>
Because you've explicitly named the template type parameters, the parameter types are selected as tree::branch*&&
and HTREEITEM&&
. This function cannot accept lvalue arguments.
In short: do not try using make_pair
or other perfect-forwarding functions with explicit template argument lists; they are not designed to be used that way.
Upvotes: 1
Reputation: 21113
First, I would be careful about constness, since you're taking the address of the reference, but expecting the pair to be a pointer to a non-constant tree::branch.
If you have lambdas, I would do the following.
std::transform(step.first->tree.begin()
, step.first->tree.end()
, std::back_inserter(steps)
[&](tree::branch& branch) { return std::make_pair(&branch, new_item); }
);
If you don't have lambda support, it might be clearer if you attempt to write the functor yourself, at least in the short term, to get clearer errors. boost::bind
is powerful, but when it fails the error messages can sometimes hide something fundamental.
struct make_step_info
{
HTREEITEM new_item;
make_step_info(HTREEITEM new_item): new_item(new_item) {};
std::pair<tree::branch*,HTREEITEM> operator()(tree::branch& branch) const
{
return std::make_pair(&branch, new_item);
}
}
/* And use it here */
std::transform(step.first->tree.begin()
, step.first->tree.end()
, std::ba_ck_inserter(steps)
make_step_info(new_item)
);
Upvotes: 0