【问题标题】:Eigen & GCC 5 : class std::binder2nd is deprecatedEigen & GCC 5:类 std::binder2nd 已弃用
【发布时间】:2015-05-29 17:45:52
【问题描述】:

我刚刚重新开始了一个搁置了几个月的项目。上次我编译它时它工作得很好,没有任何错误或警告。 然而,当我今天早些时候尝试编译它时,我收到了这个警告

attention : ‘template<class _Operation> class std::binder2nd’ is deprecated [-Wdeprecated-declarations]

当我在整个项目中使用 Eigen/Geometry 时,这个警告实际上出现了数百次

In file included from [...]/include/Eigen/src/Core/ArrayBase.h:109:0,
                 from [...]/include/Eigen/Core:350,
                 from [...]/include/Eigen/Geometry:4,
                 from [...]/include/[myproject]/types.hh:8,
                 from [...]/include/[myproject]/voronoi.hh:8

从那以后我没有更新 Eigen(使用的是 3.2.4,这仍然是今天的最后一次更新)。 不过自从上次编译之后,GCC已经更新到了5.1.0(我用的是archlinux)

问题:

  • gcc 5.1.0 是否有问题告诉我 std::binder2nd 已弃用
  • 应该更新 Eigen 吗?
  • 如何在不丢失构建的详细信息的情况下使这些特定警告静音?

回答

我认为std::bind2nd 确实已被弃用,而a commit has been done to solve that in Eigen。但是,此提交尚未与主分支合并:/(并且无法解决问题,因为 Eigen 的代码中仍然存在一些 std::bind2nd

底线是:Eigen 的最后一个稳定版本已被弃用

【问题讨论】:

  • 如果您想知道:从 C++11 开始,我们鼓励您使用 std::bind 而不是 std::bind2nd(或其姐妹 std::bind1st)。 std::bind 是可变参数模板。
  • @user465139:我知道一直使用std::bind,甚至不知道std::bind2nd。但是,这里的问题发生在 Eigen 中,我显然没有自己写
  • 感谢您的评论,现在我意识到我的评论很容易被误解。我并不是说这是你的“错”,显然这取决于 Eigen 开发人员来改变这一点。我想说的是std::bind是推荐使用的功能。我的评论是为了帮助那些可能不知道std::bind但我表达自己有点笨拙的人......
  • 警告信息本身告诉你这个警告是由-Wdeprecated-declarations标志控制的。因此,要(暂时)摆脱这些警告,请使用-Wno-deprecated-declarations 标志进行编译。
  • 您可以做的另一件事是使用-isystem 而不是-I 标志为gcc 指定Eigen 的包含目录(对于cmake,它是include_directories(SYSTEM ...))。这样就不会显示来自 Eigen 包含的警告。

标签: gcc eigen bind2nd


【解决方案1】:
  • gcc 5.1.0 是否有问题告诉我 std::binder2nd 已弃用

不,C++ 标准说它在 C++11 中已被弃用,所以如果你在 C++11 模式下编译,那么它应该被弃用。

  • 应该更新 Eigen 吗?

是的。如果它想与 C++17 兼容,因为 std::bind2nd 在 C++14 之后根本不存在。

  • 如何在不丢失构建的详细信息的情况下使这些特定警告静音?

抑制警告。在命令行上使用-Wno-deprecated-declarations 进行编译,或者在包含 Eigen 标头时在源代码中进行编译:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#include <eigen/whatever.h>
#pragma GCC diagnostic pop

或者,正如另一个答案所说,告诉 GCC 将 Eigen 标头视为系统标头,如果它们在 /usr/include 中,或者包含在 -isystem 中,或者包含在另一个标头中,则会自动发生:

#pragma GCC system_header
#include <eigen/whatever.h>

【讨论】:

  • "如果他们在/usr/include 中,这会自动发生" - 我不知道这一点。显然它不适用于子目录?
  • @Jake gcc 隐式执行 -isystem /usr/include。如果添加 -I /usr/include/eigen3,则不受此限制。
  • @MarcGlisse 您能否详细说明“不在此范围内”?将-isystem 参数应用于/usr/include/eigen3 为我删除了警告,在我得到警告之前,即使eigen3/usr/include 的子目录,隐含的isystem 目录。你是说这是意料之中的,还是不是?
  • 这是意料之中的事,与 Marc 所说的并不矛盾。他说/usr/include默认是系统目录,但是使用-I /usr/include/eigen3(注意-I不是-isystem!)使它成为一个-系统目录,所以你不会得到对/usr/include 下所有内容的常规处理。使用-isystem 没有那个效果,因为-isystem 不是-I
【解决方案2】:

我怎样才能在不丢失冗长的情况下使这些特定警告静音?

编辑 CMakeLists.txt 文件。在设置 CMAKE_CXX_FLAGS 后添加此行。

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")

先前的答案提到将其添加到#pragma 或命令行。我对#pragma 有偏见,因为后来我发现很难记住我把它放在哪里。因此,作为一般做法,我尽量避免使用#pragma。添加到命令行意味着您必须记住每次重新编译时都要输入。

【讨论】:

    【解决方案3】:

    不要使用-I 标志来包含文件,而是使用-isystem 来包含特征标头:

    g++-5 -isystem/usr/include/eigen3 source_file_here.cpp
    

    此标志适用于不符合C 标准但在生成警告时被视为误报的系统标头。特征标头的使用与系统标头非常相似,因此对于大多数用户而言,警告没有帮助,而只是令人讨厌的误报。

    归功于Ilya Popov在原始问题中的评论。

    【讨论】:

    • “此标志适用于较旧的系统标头 [...]” 这不是对标志用途的准确描述。它只是告诉编译器将该目录视为系统包含目录。作为默认情况下抑制警告的副作用,但不假定这些标头是旧的或不合格的。 GCC 自己的 C++ 库头文件被视为系统头文件,但不是不符合现代 C++ 标准的旧头文件。
    • @JonathanWakely 感谢您指出这一点,描述已更新。
    • “此标志适用于不符合 C 标准的系统头文件” 还是不行。它只是将事物视为系统标头,不假定不符合。
    • @JonathanWakely 来自 gcc.gnu.org,在我的回答中链接:“声明操作系统和运行时库接口的头文件通常不能用严格符合 C 编写. 因此,GCC 对系统头文件中的代码进行了特殊处理。”
    猜你喜欢
    • 2019-11-12
    • 1970-01-01
    • 1970-01-01
    • 2017-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-03
    相关资源
    最近更新 更多