¿Por qué no se puede chocar con libc ++ en el enlace c ++ 0x mode this boost :: program_options example?

Comstackndo este código de ejemplo para boost :: program_options: http://svn.boost.org/svn/boost/trunk/libs/program_options/example/first.cpp

… en MacOS Lion (10.7.2), usando boost-1.48.0 instalado con MacPorts:

$ clang++ -v Apple clang version 3.0 (tags/Apple/clang-211.12) (based on LLVM 3.0svn) Target: x86_64-apple-darwin11.2.0 Thread model: posix $ clang++ -std=c++0x --stdlib=libc++ -lc++ -I/opt/local/include -L/opt/local/lib -lboost_program_options first.cpp -o first Undefined symbols for architecture x86_64: "boost::program_options::options_description::options_description(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&, unsigned int, unsigned int)", referenced from: _main in cc-6QQcwm.o "boost::program_options::operator<<(std::__1::basic_ostream<char, std::__1::char_traits >&, boost::program_options::options_description const&)", referenced from: _main in cc-6QQcwm.o "boost::program_options::abstract_variables_map::operator[](std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&) const", referenced from: boost::program_options::variables_map::operator[](std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&) const in cc-6QQcwm.o "boost::program_options::detail::cmdline::set_additional_parser(boost::function1<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > >, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&>)", referenced from: boost::program_options::basic_command_line_parser::extra_parser(boost::function1<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > >, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&>) in cc-6QQcwm.o "boost::program_options::detail::cmdline::cmdline(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > > > const&)", referenced from: boost::program_options::basic_command_line_parser::basic_command_line_parser(int, char const* const*) in cc-6QQcwm.o "boost::program_options::to_internal(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&)", referenced from: std::__1::vector<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > > > boost::program_options::to_internal<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > >(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > > > const&) in cc-6QQcwm.o "boost::program_options::invalid_option_value::invalid_option_value(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&)", referenced from: void boost::program_options::validate(boost::any&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > > > const&, int*, long) in cc-6QQcwm.o "boost::program_options::validation_error::validation_error(boost::program_options::validation_error::kind_t, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&)", referenced from: std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const& boost::program_options::validators::get_single_string(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > > > const&, bool) in cc-6QQcwm.o "boost::program_options::value_semantic_codecvt_helper::parse(boost::any&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > > > const&, bool) const", referenced from: vtable for boost::program_options::typed_value in cc-6QQcwm.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) 

El mismo código comstackdo / vinculado con g ++ 4.7 instalado con MacPorts:

 $ g++-mp-4.7 -std=c++0x -I/opt/local/include -L/opt/local/lib -lboost_program_options -o first first.cpp 

… funciona bien. Al igual que el uso de clang sin libc ++:

 clang++ -std=c++0x -I/opt/local/include -L/opt/local/lib -lboost_program_options first.cpp -o first 

¿Qué pasa? ¿Por qué boost :: program_options y libc ++ no funcionan juntos?

Necesitas reconstruir el impulso utilizando clang ++ -stdlib = libc ++.

libc ++ no es compatible con binario con libstdc ++ de gcc (excepto algunas cosas de bajo nivel como el operador nuevo). Por ejemplo, std::string en libstdc ++ de gcc se vuelve a contabilizar, mientras que en libc ++ se usa la “optimización de cadenas cortas”. Si tuviera que mezclar accidentalmente estas dos cadenas en el mismo progtwig (y confundirlas con la misma estructura de datos), inevitablemente se produciría un fallo en el tiempo de ejecución.

Este accidente es exactamente lo que ocurrió en tu caso.

Para convertir este tiempo de ejecución en un error de tiempo de enlace, libc ++ utiliza una característica de lenguaje C ++ 11 denominada inline namespace de inline namespace para cambiar el ABI de std::string sin afectar la API de std::string . Es decir, para ti std::string tiene el mismo aspecto. Pero para el enlazador, std::string está siendo destrozado como si estuviera en el espacio de nombres std::__1 . Por lo tanto, el enlazador sabe que std::basic_string y std::__1::basic_string son dos estructuras de datos diferentes (la primera proviene de gcc’s libstdc ++ y la última viene de libc ++).