Reputation: 131626
After fiddling with a bunch of CMake settings in a project I'm working on, I'm encountering a linking issue which I didn't previously experience.
In a nutshell, I have a static library (.a
file) with the following symbol (demangled):
00000000000018e0 g F .text 0000000000000690 std::experimental::fundamentals_v1::optional<int> monetdb::gdk::buffer_pool::find_column<(monetdb::column_name_kind)2>(monetdb::column_name<(monetdb::column_name_kind)2> const&) const
but when I try to link an executable with this file and a compiled source using that method, I get:
main.cpp:(.text+0x6950): undefined reference to `std::experimental::optional<int> monetdb::gdk::buffer_pool::find_column<(monetdb::column_name_kind)2>(monetdb::column_name<(monetdb::column_name_kind)2> const&) const'
This is the single and only linking error, even though I instantiate a buffer_pool
and use a bunch of other methods. On the other hand, this is also the only templated method the class have.
What are the potential causes for such an this error, given the existence of the symbol in the library?
My only "clue" so far is, that the name of the optional class is different: std::experimental::optional
vs std::experimental::fundamentals_v1::optional
. Could this be the cause?
Notes:
/usr/bin/ld
is 2.32.51 .Result of g++- v
:
Using built-in specs.
COLLECT_GCC=g++-8
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/8/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 8.3.0-22' --with-bugurl=file:///usr/share/doc/gcc-8/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-8 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto --enable-link-mutex
Thread model: posix
gcc version 8.3.0 (Debian 8.3.0-22)
Upvotes: 1
Views: 757
Reputation: 131626
optional
implementation in the code outside the library.My hunch was valid, but @1201ProgramAlarm's comments led me to the solution:
The definition of std::experimental::optional
in the project using the static library wasn't taken from the standard C++ library. Instead, that was shadowed by Andrzej Krzemieński's optional implementation. Now, I have nothing bad to say about it - it's really nice; however, it does put that definition into std::experimental
, which means that if you're not careful you can mistake it for C++14's std::experimental::optional
.
In my case, the chain of #if __cplusplus > something
define it one way, #else if __cplusplus > something else
define it another way etc. was faulty - The custom optional implementation was used even when compiling with C++14.
The linker, on the other hand, doesn't confuse the different optional
implementations; in fact, libstdc++'s std::experimental::optional
is just an alias for std::experimental::fundamentals_v1::optional<int>
; so the mangled name for a function returning an optional<int>
is different. Thus even though in C++ you can't overload a function on the return type, i.e. no two functions can have the same signature except for a different return type - there's nothing preventing two mangled function names from being that way (IIANM), and that's indeed what happened in my case.
What I am not entirely sure about now is how I avoided the linking problem in the first place...
Upvotes: 1