我需要使用一些使用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 <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 <tr1/functional>
,编译正常。在我的本地机器上测试过。
gcc-4.6.3,#include <tr1/functional>
,编译正常。在我的本地机器上测试过。
gcc-5.1,没有#include <tr1/functional>
,编译正常:http://ideone.com/XrkAXT
gcc-5.1,#include <tr1/functional>
,编译错误:http://ideone.com/sRWQLn
我根本没有使用任何std::tr1::function
或std::tr1::bind
,我在遗留代码中使用的唯一内容是std::tr1::shared_ptr
对象。
为什么#include <tr1/functional>
会影响非tr1 std::function
/ std::bind
?或者这里发生了什么?
编辑:根据GNU C++ Library Manual, Chapter 3:“第二条规则的一个特例是TR1和C ++ 11设施的混合。有可能(虽然不是特别谨慎)包括TR1版本和同一翻译单元中的C ++ 11版本的标题“
答案 0 :(得分:6)
标准中有一个变化需要实现约束std::function
的构造函数,以便它不能从sun下的所有东西转换,而只能从实际的callables转换,所以libstdc ++计算返回类型: / p>
template<typename _Functor>
using _Invoke = decltype(__callable_functor(std::declval<_Functor&>())
(std::declval<_ArgTypes>()...) );
并在SFINAE中使用它。表达式SFINAE意味着如果调用表达式不编译,则转换构造函数将从重载集中删除。
问题在于__callable_functor
。它的工作是将指针指向成员,以便它们可以与普通的函数调用语法一起使用。它是一个保留的名称,所以没有其他人应该使用它...好吧,除了标准库的其他组件。我们std::__callable_functor
中的<functional>
和std::tr1::__callable_functor
中的<tr1/functional>
。因为std::tr1
是关联的命名空间(感谢std::tr1::shared_ptr<int>
的签名中使用了Foo::test
),所以最终会产生歧义。
修改:报告为bug 68995。