Fernando Felix
Fernando Felix

Reputation: 1

std::make_pair error with boost::bind in VS2010

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

Answers (2)

James McNellis
James McNellis

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

Dave S
Dave S

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

Related Questions