mfontanini
mfontanini

Reputation: 21910

Ambiguous call to std/boost move

Came across this code which doesn't compile:

#include <boost/move/utility.hpp>
#include <utility>
#include <deque>
#include <map>
#include <vector>
#include <boost/date_time/posix_time/posix_time_types.hpp>

using namespace std;

int main() {
    typedef std::pair<int, std::deque<int>> FirstPair;
    typedef std::vector<FirstPair> VectorFirstPair;
    typedef std::pair<boost::posix_time::time_duration, VectorFirstPair> SecondPair;
    typedef std::map<boost::posix_time::time_duration, SecondPair> Map;
    Map mapInstance;
    SecondPair newElement = make_pair(boost::posix_time::not_a_date_time, VectorFirstPair());
    mapInstance.insert(make_pair(boost::posix_time::seconds(10), move(newElement))).first;
}

This fails on gcc 4.8.2 using boost 1.55 (not on boost 1.54) with the following error (ideone here):

test.cpp: In function ‘int main()’:
test.cpp:17:81: error: call of overloaded ‘move(SecondPair&)’ is ambiguous
     mapInstance.insert(make_pair(boost::posix_time::seconds(10), move(newElement))).first;
                                                                                 ^
test.cpp:17:81: note: candidates are:
In file included from /usr/include/c++/4.8/bits/stl_pair.h:59:0,
                 from /usr/include/c++/4.8/utility:70,
                 from /usr/include/boost/config/no_tr1/utility.hpp:21,
                 from /usr/include/boost/config/select_stdlib_config.hpp:37,
                 from /usr/include/boost/config.hpp:40,
                 from /usr/include/boost/move/detail/config_begin.hpp:10,
                 from /usr/include/boost/move/utility.hpp:17,
                 from test.cpp:1:
/usr/include/c++/4.8/bits/move.h:101:5: note: constexpr typename std::remove_reference< <template-parameter-1-1> >::type&& std::move(_Tp&&) [with _Tp = std::pair<boost::posix_time::time_duration, std::vector<std::pair<int, std::deque<int> > > >&; typename std::remove_reference< <template-parameter-1-1> >::type = std::pair<boost::posix_time::time_duration, std::vector<std::pair<int, std::deque<int> > > >]
     move(_Tp&& __t) noexcept
     ^
In file included from test.cpp:1:0:
/usr/include/boost/move/utility.hpp:138:55: note: typename boost::remove_reference<T>::type&& boost::move(T&&) [with T = std::pair<boost::posix_time::time_duration, std::vector<std::pair<int, std::deque<int> > > >&; typename boost::remove_reference<T>::type = std::pair<boost::posix_time::time_duration, std::vector<std::pair<int, std::deque<int> > > >]
          inline typename remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT

Shouldn't this compile? Shouldn't the using namespace clause make this unambiguous? Why is the compiler choosing boost::move as a viable candidate here?

Note that this doesn't cause any errors if I remove the boost types in the types defined (replacing them with e.g. int).

Upvotes: 7

Views: 1586

Answers (2)

dhaffey
dhaffey

Reputation: 1374

As an alternative to explicitly qualifying std::move everywhere, you can define BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE, which just aliases boost::move to std::move. With that, your example compiles successfully.

Upvotes: 1

WorldSEnder
WorldSEnder

Reputation: 5044

This is because of ADL - argument dependant lookup (see this answer which is also boost related).

The problem is that the namespace boost is considered because:

§ 3.4.2 Argument-dependent name lookup

  1. ... The sets of namespaces and classes is determined entirely by the types of the function arguments (and the namespace of any template template argument). ...

Thus, because some boost-related type is a template argument of std::pair, boost::move is also considered. (imho it shouldn't because I can't figure out how to program around that ambiguity).

Upvotes: 5

Related Questions