c++ - undefined reference ,带有std::experimental::可选,尽管存在符号

标签 c++ c++14 undefined-reference libstdc++ stdoptional

在我正在处理的项目中摆弄一堆CMake设置后,我遇到了以前没有遇到过的链接问题。

简而言之,我有一个静态库(.a文件),它带有以下符号(已取消修饰):

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

但是当我尝试使用该方法将可执行文件与此文件和已编译的源链接时,我得到:
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'

即使我实例化了buffer_pool并使用了许多其他方法,这也是唯一且唯一的链接错误。另一方面,这也是该类唯一的模板化方法。

考虑到库中存在该符号,导致这种错误的潜在原因是什么?

到目前为止,我唯一的“线索”是,可选类的名称不同:std::experimental::optionalstd::experimental::fundamentals_v1::optional。这可能是原因吗?

笔记:
  • 我想问的是潜在原因,而不是实际原因(没有独立的示例就无法确定)。
  • 为了安全起见,我显式实例化了此模板化方法。
  • 编译使用的是g++ 8.3.0,而/usr/bin/ld是2.32.51。
  • 我在Devuan 3 Beowulf上(〜=没有systemd的Debian 10 Buster)。
  • 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) 
    
  • 最佳答案

    tl; dr:这可能是由于在库外部的代码中使用了自定义的optional实现引起的。

    我的直觉是有效的,但是@ 1201ProgramAlarm的评论使我找到了解决方案:

    使用静态库的项目中std::experimental::optional的定义并非来自标准C++库。相反,它被Andrzej Krzemieński's optional implementation遮盖了。现在,我对此没有什么不好说的-真的很好。但是,它确实将该定义放入std::experimental中,这意味着,如果您不小心,可以将其误认为C++ 14的std::experimental::optional

    在我的情况下,#if __cplusplus > something链以一种方式定义它,#else if __cplusplus > something else以另一种方式定义等等,这是错误的-即使使用C++ 14进行编译,也使用了自定义的可选实现。

    另一方面,链接器不会混淆不同的optional实现。实际上,libstdc++的std::experimental::optional只是std::experimental::fundamentals_v1::optional<int>的别名;因此,返回optional<int>的函数的错误名称是不同的。因此,即使在C++中,您也不能在返回类型上重载一个函数,即,除了不同的返回类型外,没有两个函数可以具有相同的签名-不能阻止两个错误的函数名那样(IIANM),这就是确实发生了我的情况。

    我现在不太确定的是首先如何避免链接问题...

    关于c++ - undefined reference ,带有std::experimental::可选,尽管存在符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60047786/

    相关文章:

    c - undefined reference : linking libraries when compiling a simple GTK+ 3. 0 Windows 上的 C 程序

    c++ - 编译器看不到我的主要功能(未定义对main的引用)

    c++ - 使用 std::swap 而不是使用 '=' 运算符进行赋值

    c++ - 由于具有循环引用的类中的 unique_ptr 或 vector 而导致核心转储

    C++ vector 存储泛型 T 类型类

    c++ - 使用变量的类型作为模板参数

    C++11 lambda 不通过引用获取 const 变量,为什么?

    c++ - 从 C++14 开始,尾随返回类型语法的合法使用

    c++ - std::array<const T, n> 与 std::array<T, n> 重载解析

    c++ - Snort 错误 : plugbase. c: undefined reference : "Setup"