【问题标题】:Using std::function with templates将 std::function 与模板一起使用
【发布时间】:2018-09-26 01:10:59
【问题描述】:

所以在它最精炼的形式中,我有这样的事情发生,

template <class T>
bool f(const T &a, const T &b, std::function<bool(const T&, const T&)> func)
{
    return func(a,b);
}

template <class T>
bool g(const T &a, const T &b)
{
    return true;
}  

但是任何尝试调用f(),使用任何东西,f('a', 'b', g)f(1, 2, g),总是导致“没有匹配的函数调用'f'”,无论我是否将变量作为常量引用传递或只是普通值或其他。我假设它无法推断出一些模板,但我不知道在哪里或为什么。

我承认,我一般对如何使用函数对象知之甚少,做这样的事情是否可能?

【问题讨论】:

  • 你需要传入一个函数作为第三个参数。
  • ... 并将缺少的 &gt; 放入您的参数列表中。仅此一项就会破坏编译。
  • 对,对。我打字匆忙,这些都存在于我的实际代码中。

标签: c++ templates std-function template-argument-deduction


【解决方案1】:

参数func 被声明为std::function,并且您试图传递一个函数指针,这需要隐式转换。 Template argument deduction不考虑隐式转换然后推演失败。

类型推导不考虑隐式转换(除了上面列出的类型调整):这是重载解析的工作,稍后会发生。

你可以显式构造一个std::function

f('a', 'b', static_cast<std::function<bool(const char&, const char&)>>(g<char>));

或显式指定模板参数(绕过模板参数推导,使隐式转换稍后生效),

f<char>('a', 'b', g<char>);    

或者干脆不要使用std::function

template <class T, class F>
bool f(const T &a, const T &b, F func)
{
    return func(a,b);
}

f('a', 'b', g<char>);

【讨论】:

  • 是的,这就是我在尝试使用 std::function 之前设置它的方式。那么......当我给它一个指向不返回布尔值的函数的指针时会发生什么?这只是需要警惕的未定义行为吗?
  • 不,例如,如果我有一个模板化函数 int f(int a, int b, F func),它只返回 func 的结果,然后我传递一个返回 char 的函数,会发生什么?
  • @Arii char 将转换为 bool 并返回。如果传递的函数返回无法转换为bool 的函数,那么您将收到一个复杂错误。
  • @Desperado17 否。同理,模板参数推导中不会考虑从 lambda 到 std::function 的隐式转换。
  • @songyuanyao 澄清一下: lambda 没有模板化。只有接受 lambda 传递给的 std::function 参数的函数才是。这会改变你的说法吗?
【解决方案2】:

我已为您解决了一些问题并添加了一些示例。这应该可以帮助您了解如何使用简单的 std::function。

#include <iostream>
#include <string>
#include <functional>

template <class T>
bool f(const T &a, const T &b, std::function<bool(const T&, const T&)> func)
{
    return func(a,b);
}

template <class T>
bool g(const T &a, const T &b)
{
    return a==b; // a simple comparator
}  

int main()
{
   int a = 1;
   int b = 1;

   // instantiate f and g as integer type functions
   if( f<int>(a,b,g<int>) == true) 
      std::cout << "true" << std::endl;
   else
      std::cout << "false" << std::endl;

   std::string c="dead";
   std::string d="beef";
   // and now as strings
   if( f<std::string>(c,d,g<std::string>) == true) 
      std::cout << "true" << std::endl;
   else
      std::cout << "false" << std::endl;
   return 0;
}

【讨论】:

  • 是的,这比我发现的任何其他内容都提供更多信息,谢谢。问题,为什么不能从g中推断出f的类型?
猜你喜欢
  • 1970-01-01
  • 2013-01-18
  • 2012-11-17
  • 1970-01-01
  • 2020-04-07
  • 1970-01-01
  • 2021-05-02
  • 1970-01-01
相关资源
最近更新 更多