Получение указателя на член std :: string :: size не может связать с libc ++, но работает с переполнением libstdStack

Я нахожусь на проекте, где мне нужно использовать libc ++. У меня возникла следующая проблема:

Когда я пытаюсь скомпилировать следующий код:

#include <string>
int main()
{
std::string::size_type (std::string::*function)() const = &std::string::size;
return 0;
}

Я получаю следующую ошибку:

ld: символы не найдены для архитектуры x86_64

Если я использую libstdc ++ вместо libc ++, я не получаю ошибок, поэтому проблема должна быть связана с libc ++.

Полный вывод ниже:

clang++ --stdlib=libc++ -v main.cpp
Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.1.0
Thread model: posix
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.10.0 -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -main-file-name main.cpp -mrelocation-model pic -pic-level 2 -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 241.9 -v -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.0 --stdlib=libc++ -fdeprecated-macro -fdebug-compilation-dir /Users/filipe/Downloads -ferror-limit 19 -fmessage-length 197 -stack-protector 1 -mstackrealign -fblocks -fobjc-runtime=macosx-10.10.0 -fencode-extended-block-signature -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -vectorize-slp -o /var/folders/8k/34ll5dcj3c5c9sph_bwk1zr00000gn/T/main-5b89bb.o -x c++ main.cpp
clang -cc1 version 6.0 based upon LLVM 3.5svn default target x86_64-apple-darwin14.1.0
ignoring nonexistent directory "/usr/include/c++/v1"#include "..." search starts here:
#include <...> search starts here:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1
/usr/local/include
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.0/include
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
/usr/include
/System/Library/Frameworks (framework directory)
/Library/Frameworks (framework directory)
End of search list.
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" -demangle -dynamic -arch x86_64 -macosx_version_min 10.10.0 -o a.out /var/folders/8k/34ll5dcj3c5c9sph_bwk1zr00000gn/T/main-5b89bb.o -lc++ -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.0/lib/darwin/libclang_rt.osx.a
Undefined symbols for architecture x86_64:
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::size() const", referenced from:
_main in main-5b89bb.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

2

Решение

Это выглядит как libc++ ошибка этой темы: _LIBCPP_INLINE_VISIBILITY и std :: string :: length который делает что-то подобное, и ответ Говарда Хиннанта таков:

Я считаю, что это связано с плохим взаимодействием в компиляторе между
внешние шаблоны и __attribute__ ((__always_inline__)). Если
std :: string не объявлен как внешний шаблон, тогда компилятор
обрисуйте элемент size (), и вы не получите эту ошибку ссылки.

На мой взгляд, Clang не должен предполагать, что внешние шаблоны имеют
определения для встроенных членов, особенно отмеченные
Always_inline, и тот факт, что это делает, является лягушачьей ошибкой, приводящей к
ошибка ссылки, которую вы видите.

Обоснование использования Always_inline в libc ++ заключается в управлении
ABI libc ++. В прошлом я наблюдал, как компиляторы используют разные
эвристика от выпуска к выпуску при создании inline / схемы
решение. Это может привести к тому, что код будет тихо добавлен и удален
от дизлиба. С использованием Always_inline я говорю
компилятор, чтобы никогда не добавлять этот код в двоичный файл libc ++. dylib.

Каждый из макросов, определенных и используемых libc ++, может быть переопределен.

_LIBCPP_INLINE_VISIBILITY управляет назначением встроенной функции и по умолчанию:

#ifndef _LIBCPP_INLINE_VISIBILITY
#define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__visibility__("hidden"), __always_inline__))
#endif

Вы можете отключить это с:

-D_LIBCPP_INLINE_VISIBILITY = «»

И внешние шаблоны сделаны с:

#ifndef _LIBCPP_EXTERN_TEMPLATE
#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
#endif

Этот последний сложнее «выключить». Заклинание это:

-D’_LIBCPP_EXTERN_TEMPLATE (…) =»

Использование одного или обоих из этих обходных путей заставит вашу ссылку замолчать
ошибка. Но сообщение об ошибке в Clang может быть лучше в долгосрочной перспективе
решение.

Я не могу воспроизвести это на coliru но я могу на wandbox и с помощью оптимизации, которая использует -O2 флаг убирает проблему Я не смог заставить wandbox принять -D варианты, предложенные выше, поэтому не уверен, что это работает.

На моей локальной машине работает решение Говарда:

clang++ -D_LIBCPP_INLINE_VISIBILITY="" -D'_LIBCPP_EXTERN_TEMPLATE(...)='

Я не нашел сообщение об ошибке, если я не нахожу, это может иметь смысл подать один.

2

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

Изучив информацию Shafik Yaghmour, я нашел решение, которое не требует изменения флагов компиляции.

Решение заключается в том, чтобы заставить компилятор создавать экземпляр внешнего шаблона. Окончательный код следующий:

#include <string>

template class std::basic_string<char>;

int main()
{
std::string::size_type (std::string::*function)() const = &std::string::size;
return 0;
}

Больше информации здесь: использование внешнего шаблона (C ++ 11)

0

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