C ++用另一个函数包装一个通用的std :: tr1 :: function

时间:2011-08-27 06:40:29

标签: c++

如何用另一个函数包装泛型 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)>)’

2 个答案:

答案 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::bindtr1::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;
}
  1. (一个小问题)wrapped是一个函数模板,因此无法绑定。你需要一个功能。幸运的是,您只需指定wrapped<T>
  2. (更大的问题)bind不返回std::tr1::function<>,它返回一些其他函数对象。您无法调用与该对象接受std::tr1::function<>的函数模板,因为函数模板没有用户定义的参数转换。您需要自己明确地进行转换。我不确定你是否可以在没有一直到C ++ 11的情况下消除这种情况。在C ++ 11中,您可以使用auto和后缀结果类型表示法重写wrap,以便它接受任何内容,而不仅仅是function<int(T)>
  3. 编辑 Fiktik是正确的,因为它足以说wrap<int>。隐式参数转换确实可以使用它。