如何用另一个函数包装泛型 C ++ std :: tr1 :: function对象,以便首先执行此函数,然后执行包装函数?我试过了:
#include <tr1/functional>
template <typename T>
int wrapped(const std::tr1::function<int(T)>& f, T t)
{
return f(t);
}
template <typename T>
std::tr1::function<int(T)> wrap(const std::tr1::function<int(T)>& f)
{
return std::tr1::bind(&wrapped, f, std::tr1::placeholders::_1);
}
int foo(int i) { return i; }
int main(int argc, char** argv)
{
std::tr1::function<int(int)> f =
wrap(std::tr1::bind(&foo, std::tr1::placeholders::_1));
f(1);
return 0;
}
但是这会返回编译器错误(g ++):
wrap.cpp: In function ‘int main(int, char**)’:
wrap.cpp:22: error: no matching function for call to ‘wrap(std::tr1::_Bind<int (* ()(std::tr1::_Placeholder<1>))(int)>)’
答案 0 :(得分:2)
我在你的代码中看到两个问题。首先,wrapped
不是函数,它是函数模板,因此在生成的程序中不存在。您不能获取功能模板的地址。您应该指定此模板的实例化以获取地址:
template <typename T>
std::tr1::function<int(T)> wrap(const std::tr1::function<int(T)>& f)
{
return std::tr1::bind(&wrapped<T>, f, std::tr1::placeholders::_1);
}
第二个(那就是你的编译器试图告诉你的)你必须在调用wrap
时明确指定一个模板参数。编译器无法从提供的参数中推导出参数。
std::tr1::function<int(int)> f =
wrap<int>(std::tr1::bind(&foo, std::tr1::placeholders::_1));
我真的不明白std::bind
或tr1::bind
在内部是如何运作的。但我知道返回的类型与简单的函数指针非常不同,因此不允许编译器清楚地读取模板参数推导的类型。因此,在这些情况下,您需要明确指定类型。
答案 1 :(得分:2)
此代码存在两个问题。一个很容易修复,另一个不那么容易。
#include <tr1/functional>
template <typename T>
int wrapped(const std::tr1::function<int(T)>& f, T t)
{
return f(t);
}
template <typename T>
std::tr1::function<int(T)> wrap(const std::tr1::function<int(T)>& f)
{
return std::tr1::bind(&wrapped<T>, f, std::tr1::placeholders::_1); // <- prob 1
}
int foo(int i) { return i; }
int main(int argc, char** argv)
{
std::tr1::function<int(int)> f =
wrap(std::tr1::function<int(int)>(std::tr1::bind(&foo, // <- prob 2
std::tr1::placeholders::_1)));
f(1);
return 0;
}
wrapped
是一个函数模板,因此无法绑定。你需要一个功能。幸运的是,您只需指定wrapped<T>
。bind
不返回std::tr1::function<>
,它返回一些其他函数对象。您无法调用与该对象接受std::tr1::function<>
的函数模板,因为函数模板没有用户定义的参数转换。您需要自己明确地进行转换。我不确定你是否可以在没有一直到C ++ 11的情况下消除这种情况。在C ++ 11中,您可以使用auto
和后缀结果类型表示法重写wrap
,以便它接受任何内容,而不仅仅是function<int(T)>
。 编辑 Fiktik是正确的,因为它足以说wrap<int>
。隐式参数转换确实可以使用它。