问题
I have a bit of code (which I didn't write, but am trying to compile) -- iostream_combo.cc--, and doing so gives me the following error:
./moses/moses/comboreduct/combo/iostream_combo.cc: In function ‘std::__cxx11::string opencog::combo::l2ph(const string&, const std::vector<std::__cxx11::basic_string<char> >&)’: ./moses/moses/comboreduct/combo/iostream_combo.cc:543:64: error: call of overloaded ‘distance(std::vector<std::__cxx11::basic_string<char> >::const_iterator, __gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >&)’ is ambiguous arity_t idx = distance(labels.begin(), found_it) + 1; ^ In file included from /usr/include/c++/8/bits/stl_algobase.h:66, from /usr/include/c++/8/bits/char_traits.h:39, from /usr/include/c++/8/ios:40, from /usr/include/c++/8/ostream:38, from /usr/include/c++/8/iostream:39, from ./moses/moses/comboreduct/combo/iostream_combo.h:28, from ./moses/moses/comboreduct/combo/iostream_combo.cc:24: /usr/include/c++/8/bits/stl_iterator_base_funcs.h:138:5: note: candidate: ‘typename std::iterator_traits<_Iterator>::difference_type std::distance(_InputIterator, _InputIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; typename std::iterator_traits<_Iterator>::difference_type = long int]’ distance(_InputIterator __first, _InputIterator __last) ^~~~~~~~ In file included from /usr/local/include/boost/range/distance.hpp:18, from /usr/local/include/boost/range/functions.hpp:21, from /usr/local/include/boost/range/iterator_range_core.hpp:38, from /usr/local/include/boost/lexical_cast.hpp:30, from ./moses/moses/comboreduct/combo/iostream_combo.h:30, from ./moses/moses/comboreduct/combo/iostream_combo.cc:24: /usr/local/include/boost/iterator/distance.hpp:49:9: note: candidate: ‘constexpr typename boost::iterators::iterator_difference<Iterator>::type boost::iterators::distance_adl_barrier::distance(SinglePassIterator, SinglePassIterator) [with SinglePassIterator = __gnu_cxx::__normal_iterator<const std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; typename boost::iterators::iterator_difference<Iterator>::type = long int]’ distance(SinglePassIterator first, SinglePassIterator last) ^~~~~~~~
I'm using Ubuntu 16.04 x64, Boost 1.68 and gcc 8.2. So, the steps to reproduce the problem would be as follows:
- On Ubuntu 16.04
- install
gcc-8
- Use it to build boost 1.68 from source
- Git clone the moses repository sand follow the instructions from there: basically 1) git clone and build
cogutil
; 2) try to makemoses
:cd build
,cmake ..
,make
.
I understand C++ enough (I think) that I can see that the call to std::distance
is overloaded. What I don't see is the way to disambiguate it, although I guess it must include some re-writing of found_it
or some explicit castings instead of auto
.
回答1:
The calls are like:
arity_t idx = distance(labels.begin(), found_it) + 1;
This means that distance
is found via ADL and hence all associated namespaces are considered. This might prove problematic if e.g. there are two namespaces providing an equally applicable overload for distance
:
Live On Coliru
#include <iterator>
#include <vector>
namespace OyVeh {
struct X { };
template <typename It>
size_t distance(It, It) { return 42; } // just to throw in a wrench
}
int main() {
std::vector<OyVeh::X> v{3};
auto f = v.begin();
auto l = v.end();
// now f and l have both `::std` and `::OyVeh` as associated namespaces. The following is ambiguous:
return distance(f, l);
}
There are roughly 2 ways to fix it:
- remove the ambigious
distance
declaration from the associated namespace (this might not be possible if e.g. the ones competing arestd::distance
andboost::distance
) - edit the calls to remove the reliance on ADL (e.g. qualify them like
std::distance(...)
or parenthesize them(distance)(...)
)
Showing the workarounds:
Live On Coliru
{
using OyVeh::distance;
return (distance)(f, l); // parentheses suppress ADL
}
return std::distance(f, l); // also works, obviously
return OyVeh::distance(f, l); // but beware the meaning might change
来源:https://stackoverflow.com/questions/52122093/error-call-of-overloaded-distance-is-ambiguous