#include <functional>
#include <memory>
#include <iostream>
using namespace std;
class Foo
{
public:
void Bar() { std::cout << "Foo::Bar" << std::endl; }
};
int main()
{
shared_ptr<Foo> foo(new Foo);
function<void(Foo*)> f1(bind(&Foo::Bar, placeholders::_1));
function<void(shared_ptr<Foo>)> f2(bind(&Foo::Bar, placeholders::_1));
return 0;
}
GCC对象使用shared_ptr签名分配给函数对象的第二个绑定语句。这是错误输出。
/ usr / include / c ++ / 4.5 / functional:2103 | 6 |实例化 'std :: function&lt; _Res(_ArgTypes ...)&gt; :: function(_Functor,typename std :: enable_if&lt;(!std :: is_integral&lt; _Functor&gt; :: value), std :: function&lt; _Res(_ArgTypes ...)&gt; :: _ Useless&gt; :: type)[with _Functor = std :: _ Bind(std :: _ Placeholder&lt; 1&gt;)&gt;,_Res = void,_ArgTypes = {std :: shared_ptr},typename std :: enable_if&lt;(! std :: is_integral&lt; _Functor&gt; :: value),std :: function&lt; _Res(_ArgTypes ...)&gt; :: _ Useless&gt; :: type = 的std ::函数)GT; :: _无用]” | /home/craig/work/litd/test/main.cpp:29|97 |从这里实例化| /usr/include/c++/4.5/functional | 1713|error:无法匹配来电 “(标准:: _绑定(STD :: _占位符&LT 1为卤素;)&GT) (STD :: shared_ptr的)” | || ===构建完成:1个错误,0个警告 === |
编辑: 更神秘的是,当我将include头更改为它们的tr1等价物时,它确实可以编译。
#include <tr1/functional>
#include <tr1/memory>
#include <iostream>
using namespace std::tr1;
class Foo
{
public:
void Bar() { std::cout << "Foo::Bar" << std::endl; }
};
int main()
{
shared_ptr<Foo> foo(new Foo);
function<void(Foo*)> f1(bind(&Foo::Bar, placeholders::_1));
function<void(shared_ptr<Foo>)> f2(bind(&Foo::Bar, placeholders::_1));
return 0;
}
答案 0 :(得分:1)
它看起来像g ++的std::function
或std::bind
实现中的错误,具体取决于您是否可以使用bind(&Foo::Bar, placeholders::_1)
调用foo
返回的对象;如果这样做:
auto fn2 = bind(&Foo::Bar, placeholders::_1);
fn2(foo);
那么g ++的std::function
实现似乎不完整。否则,std::bind
的实现似乎不完整。
[20.8.9.1.2]函数模板bind
状态:
template<class F, class... BoundArgs> unspecified bind(F&& f, BoundArgs&&... bound_args);
...
返回:具有弱结果类型(20.8.2)的转发调用包装器
g
。g(u1, u2, ..., uM)
的效果应为INVOKE(fd, v1, v2, ..., vN, result_of::type)
[20.8.2]要求声明:
如下定义
INVOKE(f, t1, t2, ..., tN)
:-
(t1.*f)(t2, ..., tN)
当f
是指向类T
的成员函数的指针时,t1
是T
类型的对象或对T
的引用类型为T
的对象或对从((*t1).*f)(t2, ..., tN)
派生的类型的对象的引用;-
f
当T
是指向类t1
的成员函数的指针时,&Foo::Bar
不是上一项中描述的类型之一;...
绑定u1
时,返回的“转发调用包装器”将使用一个参数U1
。调用其类型BoundArgs
。在[20.8.9.1.2]中进一步说明,因为_1
中的第一个模板参数类型是V1
占位符类型,所以类型U1&&
是std::shared_ptr<Foo>
。< / p>
应允许将bind(&Foo::Bar, placeholders::_1)
传递给#include <functional>
#include <memory>
#include <iostream>
using namespace std;
class Foo
{
public:
void Bar() { std::cout << "Foo::Bar" << std::endl; }
};
int main()
{
shared_ptr<Foo> foo(new Foo);
function<void(Foo*)> f1(bind(&Foo::Bar, placeholders::_1));
//function<void(shared_ptr<Foo>)> f2(bind(&Foo::Bar, placeholders::_1));
auto fn2 = bind(&Foo::Bar, placeholders::_1);
fn2(foo);
return 0;
}
返回的转发调用包装器,因为[20.8.2]的情况2适用。
编辑:我在Windows(MinGW)上使用与您相同版本的g ++ 4.5.2。对我来说,以下编译就好了:
std::function
因此,似乎应该责怪g ++对 auto fn2 = bind(&Foo::Bar, placeholders::_1);
fn2(std::shared_ptr<Foo>(foo));
的实现。
EDIT2:以下失败:
std::bind
SO7408263.cpp:19:31:错误:无法调用'(std :: _ Bind(std :: _ Placeholder&lt; 1&gt;)&gt;)(std :: shared_ptr)'
毕竟也许是{{1}}。
答案 1 :(得分:0)
该函数将重载->*
以使用指向成员的指针。我相信shared_ptr
不提供此功能。 TR1规范可能已经强制要求专业化,但C ++ 11可能没有。在Visual Studio中,C ++ 11 shared_ptr
被定义为TR1版本,这可以解释其中的差异。