【问题标题】:Mixing std::tr1::shared_ptr with std::function / std::bind causes compiler errors with newer gcc将 std::tr1::shared_ptr 与 std::function / std::bind 混合使用较新的 gcc 会导致编译器错误
【发布时间】:2015-12-17 12:33:58
【问题描述】:

我需要使用一些使用std::tr1::shared_ptr 的旧代码。我需要包含的标头同时具有#include <tr1/memory> 和#include <tr1/functional>。在我的代码中,我想使用std::function 和std::bind,因为我们的编译器支持这些。

这适用于 gcc 4.6.3 和 4.7.3。在 4.9.2、5.1.x 和 5.2.0 中,这会导致编译器错误。这似乎是由于<tr1/functional>-include 而发生的。

我写了一个小例子来重现这个问题:

#include <tr1/memory>
#include <functional>
#include <tr1/functional>

struct Foo {
    void test(std::tr1::shared_ptr<int> i) {}
};

int main() {
    Foo f;
    std::function<void(std::tr1::shared_ptr<int>)> func = std::bind(&Foo::test, f, std::placeholders::_1);

    return 0;
}

gcc-4.6.3,没有#include &lt;tr1/functional&gt;,编译OK。在我的本地机器上测试。

gcc-4.6.3,带有#include &lt;tr1/functional&gt;,编译OK。在我的本地机器上测试。

gcc-5.1,没有#include &lt;tr1/functional&gt;,编译OK:http://ideone.com/XrkAXT

gcc-5.1,带有#include &lt;tr1/functional&gt;,编译器错误:http://ideone.com/sRWQLn

我根本没有使用任何std::tr1::function 或std::tr1::bind,我在遗留代码中唯一使用的是std::tr1::shared_ptr 对象。

为什么#include &lt;tr1/functional&gt; 会影响非tr1 std::function / std::bind?或者这里发生了什么?

编辑:根据GNU C++ Library Manual, Chapter 3:“第二条规则的一个特例是 TR1 和 C++11 工具的混合。有可能(尽管不是特别谨慎)包括 TR1 版本和同一个翻译单元中的 C++11 版本的 header"

【问题讨论】:

  • Clang 更有用,它报告了ambiguity。我猜是 ADL。
  • 不是因为你同时包含了函数式和 tr1/函数式吗?
  • 是 boost 的 tr1/functional 吗?
  • @sop No.(评论太短)
  • 使用tr1的旧代码是什么?我认为它应该移植到 c++11,没有更多的 tr1。 tr1 在 C++11 中不再存在。我只使用内存(不是 tr1/内存),功能(不是 tr1/功能)。我认为您应该将所有 std::tr1:: 替换为 std::。还是您使用 2 个编译器?

标签: c++ c++11 gcc tr1


【解决方案1】:

标准发生了变化,要求实现约束std::function的构造函数,使其不能从阳光下的所有东西转换,而只能从实际的可调用对象转换,因此libstdc++计算返回类型:

template<typename _Functor>
using _Invoke = decltype(__callable_functor(std::declval<_Functor&>())
                         (std::declval<_ArgTypes>()...) );

并在 SFINAE 中使用它。表达式 SFINAE 表示如果调用表达式未编译,则从重载集中删除转换构造函数。

问题在于__callable_functor。它的工作是包装指向成员的指针,以便它们可以与正常的函数调用语法一起使用。它是一个保留名称,所以没有其他人应该使用它......好吧,除了标准库的其他组件。我们在&lt;functional&gt; 中有std::__callable_functor,在&lt;tr1/functional&gt; 中有std::tr1::__callable_functor。而且因为std::tr1 是一个关联的命名空间(感谢std::tr1::shared_ptr&lt;int&gt; 在Foo::test 的签名中的使用),所以最终会产生歧义。

编辑:报告为bug 68995。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-13
    • 1970-01-01
    • 1970-01-01
    • 2014-03-25
    • 2012-06-11
    • 1970-01-01
    • 1970-01-01
    • 2013-09-01
    相关资源
    最近更新 更多