Взаимодействие модулей Clang с std & lt; iterator & gt; и & lt; boost / move / iterator.hpp & gt;

(См. Конец вопроса для получения информации о конкретных версиях Boost и Clang, которые я использую)

Компиляция в Clang от master / HEAD, используя новый экспериментальный -fmodules Я получаю ошибку сборки при компиляции следующего файла с параметрами командной строки, показанными ниже:

#include <iterator>
#include <boost/move/iterator.hpp>

Скомпилируйте команду и ошибку:

anhall@leviathan: <path-to-clang-install-from-master>/bin/clang++ -o file.o -c file.cpp --std=c++1z -stdlib=libc++ -fmodules

In file included from file.cpp:2:
In file included from /usr/local/include/boost/move/iterator.hpp:27:
/usr/local/include/boost/move/detail/iterator_traits.hpp:60:17: error: reference to 'random_access_iterator_tag' is ambiguous
typedef std::random_access_iterator_tag   iterator_category;
^
/Users/anhall/impersonal/code/llvm-reflexpr/install/bin/../include/c++/v1/iterator:438:30: note: candidate found by name lookup is 'std::__1::random_access_iterator_tag'
struct _LIBCPP_TYPE_VIS_ONLY random_access_iterator_tag : public bidirectional_iterator_tag {};
^
/usr/local/include/boost/move/detail/iterator_traits.hpp:34:8: note: candidate found by name lookup is 'std::random_access_iterator_tag'
struct random_access_iterator_tag;
^
/usr/local/include/boost/move/detail/iterator_traits.hpp:71:17: error: reference to 'random_access_iterator_tag' is ambiguous
typedef std::random_access_iterator_tag   iterator_category;
^
/Users/anhall/impersonal/code/llvm-reflexpr/install/bin/../include/c++/v1/iterator:438:30: note: candidate found by name lookup is 'std::__1::random_access_iterator_tag'
struct _LIBCPP_TYPE_VIS_ONLY random_access_iterator_tag : public bidirectional_iterator_tag {};
^
/usr/local/include/boost/move/detail/iterator_traits.hpp:34:8: note: candidate found by name lookup is 'std::random_access_iterator_tag'
struct random_access_iterator_tag;
^
In file included from file.cpp:2:
/usr/local/include/boost/move/iterator.hpp:196:17: error: reference to 'output_iterator_tag' is ambiguous
typedef std::output_iterator_tag    iterator_category;
^
/Users/anhall/impersonal/code/llvm-reflexpr/install/bin/../include/c++/v1/iterator:435:30: note: candidate found by name lookup is 'std::__1::output_iterator_tag'
struct _LIBCPP_TYPE_VIS_ONLY output_iterator_tag {};
^
/usr/local/include/boost/move/detail/iterator_traits.hpp:35:8: note: candidate found by name lookup is 'std::output_iterator_tag'
struct output_iterator_tag;
^
In file included from file.cpp:2:
/usr/local/include/boost/move/iterator.hpp:238:17: error: reference to 'output_iterator_tag' is ambiguous
typedef std::output_iterator_tag    iterator_category;
^
/Users/anhall/impersonal/code/llvm-reflexpr/install/bin/../include/c++/v1/iterator:435:30: note: candidate found by name lookup is 'std::__1::output_iterator_tag'
struct _LIBCPP_TYPE_VIS_ONLY output_iterator_tag {};
^
/usr/local/include/boost/move/detail/iterator_traits.hpp:35:8: note: candidate found by name lookup is 'std::output_iterator_tag'
struct output_iterator_tag;
^
In file included from file.cpp:2:
/usr/local/include/boost/move/iterator.hpp:278:17: error: reference to 'output_iterator_tag' is ambiguous
typedef std::output_iterator_tag    iterator_category;
^
/Users/anhall/impersonal/code/llvm-reflexpr/install/bin/../include/c++/v1/iterator:435:30: note: candidate found by name lookup is 'std::__1::output_iterator_tag'
struct _LIBCPP_TYPE_VIS_ONLY output_iterator_tag {};
^
/usr/local/include/boost/move/detail/iterator_traits.hpp:35:8: note: candidate found by name lookup is 'std::output_iterator_tag'
struct output_iterator_tag;
^
5 errors generated.

Если я удалю #include <iterator> или переместить его после #include <boost/move/iterator.hpp>, ошибки исчезают.

Вопрос: Является ли это просто побочным продуктом библиотек Boost (в частности, Boost Move), который не готовится для модулей с файлами карт модулей Clang? Может ли это быть ошибкой в ​​файлах карты модулей, реализованной Clang для libc ++, или даже ошибкой в ​​самой реализации модулей?

Интересно, что я могу устранить ошибку, закомментировав строки 28-28 boost/move/detail/iterator_traits.hpp:

// #include <boost/move/detail/std_ns_begin.hpp>
// BOOST_MOVE_STD_NS_BEG
//
// struct input_iterator_tag;
// struct forward_iterator_tag;
// struct bidirectional_iterator_tag;
// struct random_access_iterator_tag;
// struct output_iterator_tag;
//
// BOOST_MOVE_STD_NS_END
// #include <boost/move/detail/std_ns_end.hpp>

Версии в использовании

Boost 1.61

Clang из кончика мастер-ветви в зеркале github LLVM, по состоянию на 7 декабря 2016 г. (технически он из форка LLVM, но только в мастер-ветви, идентичной собственной мастер-ветви LLVM):

clang version 4.0.0 (https://github.com/matus-chochlik/clang.git b9cb1c8a1ebf52695372de12c7b04c8ef1bd8b4e) (https://github.com/llvm-mirror/llvm.git b60c7b1f61eabbe971d08568adb790a7cfc6a403)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Users/anhall/impersonal/code/llvm-reflexpr/install/bin

7

Решение

Я полагаю, что это было вызвано проблемой с модулем libc ++ module.modulemap, которую я вчера исправил в r289028. Эта ошибка вызвала _LIBCPP_VERSION макрос не экспортируется libc ++, когда модули включены.

Посмотрев на boost/move/detail/iterator_traits.hpp кажется, что если _LIBCPP_VERSION не определено, оно будет неправильно сконфигурировано и в итоге объявит совершенно разные определения тегов итератора. (В частности, он будет определять их непосредственно в пространстве имен std а не в пространстве имен управления версиями libc ++).

Если вы пересоберите LLVM и libc ++, то должен исправить вашу проблему. Если не смело сообщить об ошибке.

PS. Кажется, я просто на шаг впереди.

4

Другие решения

На данный момент я могу говорить только о повышении 1.59.1, но оно также явно предполагает, что с libc ++ можно встретиться только при сборке с помощью clang:

#if defined(__clang__) && defined(_LIBCPP_VERSION)
// ...
#else
// ...
#endif

Это вызывает (почти) точно такую ​​же ошибку, как показано выше, даже в Mac OS X 10.9, которая имеет libc ++, предшествующую введению регрессии libc ++, которая вызвала проблему, обсуждаемую в этом потоке.

2

По вопросам рекламы [email protected]