ошибка: вызов перегруженного расстояния неоднозначен - PullRequest
0 голосов
/ 31 августа 2018

У меня есть немного кода (который я не писал, но пытаюсь скомпилировать) - iostream_combo.cc -, и это дает мне следующую ошибку:

./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)
     ^~~~~~~~

Я использую Ubuntu 16.04 x64, Boost 1.68 и gcc 8.2. Итак, шаги по воспроизведению проблемы будут следующими:

  1. В Ubuntu 16.04
  2. установка gcc-8
  3. Используйте его для создания надстройки 1.68 из источника
  4. Git clone moses репозиторий sand, следуйте оттуда инструкциям: в основном 1) git clone и build cogutil; 2) попробуйте сделать moses: cd build, cmake .., make.

Я достаточно понимаю C ++ (мне кажется), что я вижу, что вызов std::distance перегружен. То, что я не вижу, - это способ устранения неоднозначности, хотя я предполагаю, что оно должно включать некоторую переписывание found_it или некоторые явные отливки вместо auto.

1 Ответ

0 голосов
/ 31 августа 2018

Звонки, как:

    arity_t idx = distance(labels.begin(), found_it) + 1;

Это означает, что distance найдено через ADL и, следовательно, рассматриваются все связанные пространства имен. Это может оказаться проблематичным, если, например, есть два пространства имен, обеспечивающие одинаково применимую перегрузку для 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);
}

Существует примерно 2 способа исправить это:

  • удалить неоднозначное объявление distance из связанного пространства имен (это может быть невозможно, если, например, конкурируют std::distance и boost::distance)
  • отредактируйте вызовы, чтобы исключить зависимость от ADL (например, укажите их как std::distance(...) или заключите в скобки (distance)(...))

Отображение обходных путей:

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
...