C ++候选模板传递lambda作为std :: function的参数时忽略错误

时间:2016-12-10 02:29:58

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

这是我在C ++中遇到的模板问题的一般骨架版本。在div { padding: 20px; } button { margin: -20px 0 0 -20px; } 调用时,我无法弄清楚如何将bar函数模板识别为合理的候选者。

foo

修改

代码的大量简化版本,同样的错误。我正在寻找上述版本的解决方案,而不是这个。

#include <iostream>
#include <cstdlib>
#include <unordered_map>

template<class T>
std::unordered_map<std::string, T> getStr2TMap() {
  return {}; // suppose logic here is a bit more involved
}

template<class T>
std::unordered_map<int, T> getInt2TMap() {
  return {}; // suppose logic here is a bit more involved
}

template<class U, class T>
void bar(
  const std::function<void (std::unordered_map<U, T>&&)>& baz
) {
  if (rand() % 2 > 0) {
    baz(getInt2TMap<T>());
  } else {
    baz(getStr2TMap<T>());
  }
}

template<class T>
void foo(
  const std::unordered_map<std::string, T>& map1
) {
  bar([&map1](auto&& map2) {
    // do some things with map1 and map2
  });
}

int main() {
  std::unordered_map<std::string, int> myMap;
  foo<int>(myMap);
}

2 个答案:

答案 0 :(得分:3)

显示的代码会尝试为以下类型推断TU

std::function<void (std::unordered_map<U, T>&&)>

推导尝试是针对传递给模板函数的lambda参数:

[&map1](auto&& map2) {}

问题是lambda不是某种std::function。这是一个:

  

...唯一未命名的非联合非聚合类的临时对象   类型,称为“封闭”类型,......

Cite

换句话说,lambda对象是一个具有operator()的类的实例,它执行lambda代码(捕获的对象被变换为未命名类的成员)。因此,由于它不是std::function,因此无法从中推断出std::function的类型。

由于它是可调用类型,因此可以将其转换为std::function,但是:

bar(static_cast<std::function<void(std::unordered_map<std::string, T> &&)>>
      ([&map1](auto&& map2) {
          // do some things with map1 and map2
      }));
}

即可识别bar()模板功能。

但显示的代码仍然存在第二个问题:

  if (rand() % 2 > 0) {
    baz(getInt2TMap<T>());
  } else {
    baz(getStr2TMap<T>());
  }

根据骰子的滚动,代码将尝试传递无序的字符串映射,或者将无序的整数映射传递给baz()

那......不会起作用。在游戏的这个阶段,baz是某种std::function。它不是模板。因此,它只能采用一种类型的参数。

如果您添加static_cast,请将bar()添加为:

 baz(getStr2TMap<T>());

为了匹配调用者传递无序的字符串映射这一事实,生成的代码应该编译。

bar()内发生的事情是一个单独的问题。使用static_cast回答了如何识别候选模板bar的问题。

答案 1 :(得分:1)

Sam对Ubar如何不一致做了很好的观察。但是在你的简单例子中,为什么在你写的时候会遇到const std::function<void (std::unordered_map<int, T>&&)>&的所有麻烦:

#include <iostream>
#include <functional>
#include <unordered_map>

template<class T, class Func>
void foo(
  Func bar
) {
  std::unordered_map<int, T> myMap;
  bar(myMap);
}

int main() {
  // needs the hint for T, since it isn't used anywhere
  foo<int>([](auto&& m) {
  });
}