变体模板,类型演绎和std :: function

时间:2015-09-13 23:58:02

标签: c++ c++11 variadic-templates std-function

我试图创建一个模板函数,可以通过任何类型和数量的参数传递一些其他函数,并将其绑定到std::function。我设法做到了:

#include <iostream>
#include <functional>

int foo(int bar)
{
  std::cout << bar << std::endl;
  return bar;
}

template <typename Ret, typename... Args>
std::function<Ret (Args...)> func(std::function<Ret (Args...)> f)
{
  return f;
}

int main()
{
  //auto barp = func(foo); // compilation error
  auto bar  = func(std::function<void (int)>(foo));

  bar (0); // prints 0
}

我想调用auto barp = func(foo);并推断出类型,但这一行会产生以下编译错误:

error: no matching function for call to ‘func(void (&)(int))’
    auto barp = func(foo);
                        ^
note: candidate is:
note: template<class Ret, class ... Args> std::function<_Res(_ArgTypes ...)> func(std::function<_Res(_ArgTypes ...)>)
 std::function<Ret (Args...)> func(std::function<Ret (Args...)> f)
                              ^
note:   template argument deduction/substitution failed:
note:   mismatched types ‘std::function<_Res(_ArgTypes ...)>’ and ‘int (*)(int)’
   auto barp = func(foo);
                       ^

为什么要将std::function<_Res(_ArgTypes ...)>int (*)(int)匹配?我觉得我应该以某种方式将编译器扩展到_Res(_ArgTypes ...)int(int),但是如何?

1 个答案:

答案 0 :(得分:2)

一个函数不是std::function,它可以转换为一个函数。 但是,你可以推断出一个函数的参数,除非有关重载的歧义。

#include <iostream>
#include <functional>

int foo(int bar)
{
  std::cout << bar << std::endl;
  return 0;
}

// Will cause error.
//int foo(double); 

template <typename Ret, typename... Args>
std::function<Ret (Args...)> func(Ret f(Args...))
{
  return f;
}

int main()
{
  auto bar = func(foo);
  bar (0); // prints 0
}

您想要对原始std::function做什么与此相似,显然不起作用:

template<typename T>
struct A
{
  A(T);  
};

template<typename T>
void func(A<T> a);

int main()
{
    func(42);
}

42不是A,但它可以转换为一个。但是,将其转换为一个则需要T已知。