简体   繁体   English

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

[英]C++ Candidate Template Ignored error when passing lambda as argument for std::function

This is a general, skeleton version of a template problem I'm having in C++. 这是我在C ++中遇到的模板问题的一般骨架版本。 I can't quite figure out how to get the bar function template to be recognized as a plausible candidate when invoked from foo . 我无法弄清楚如何在从foo调用时将bar函数模板识别为合理的候选者。

#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);
}

EDIT 编辑

Much simplified version of the code, same error. 很多简化版本的代码,同样的错误。 I'm looking for solutions to the above version though, not this one. 我正在寻找上述版本的解决方案,而不是这个。

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

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

int main() {
  foo([](auto&& m) {
  });
}

The shown code attempts to deduce T and U for the following type 显示的代码尝试推导出以下类型的TU

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

The deduction attempt is for the lambda parameter passed to the template function: 推导尝试是针对传递给模板函数的lambda参数:

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

The problem is that a lambda is not a std::function of some kind. 问题是lambda不是某种std::function It is a: 它是一个:

...temporary object of unique unnamed non-union non-aggregate class type, known as "closure" type,... ...唯一未命名的非联合非聚合类类型的临时对象,称为“闭包”类型,...

( Cite ) 引用

Put in another way, a lambda object is an instance of a class with an operator() that executes the lambda code (and captured objects get transmogrified into members of the unnamed class). 换句话说,lambda对象是一个类的实例,其中operator()执行lambda代码(捕获的对象被变换为未命名类的成员)。 As such, since it is not a std::function , it is not possible to deduce std::function 's types from it. 因此,由于它不是std::function ,因此无法从中推导出std::function的类型。

Since it is a callable type, it can be converted to a std::function , though: 因为它是一个可调用类型,所以它可以转换为std::function ,但是:

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

That'll get the bar() template function recognized. 这将获得bar()模板功能的识别。

But there's still a second problem with the shown code: 但是显示的代码仍然存在第二个问题:

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

Depending on the roll of the dice, the code will attempt to pass either an unordered map of strings, or an unordered map of ints to baz() . 根据骰子的滚动,代码将尝试传递无序的字符串映射,或者将无序的int映射传递给baz()

That's ...not going to work. 那......不会起作用。 At this stage of the game, baz is a std::function of some kind. 在游戏的这个阶段, baz是某种std::function It's not a template. 它不是模板。 As such, it can only take a parameter of one type. 因此,它只能采用一种类型的参数。

If you add that static_cast , and make bar() a: 如果你添加static_cast ,并使bar() a:

 baz(getStr2TMap<T>());

to match the fact that the caller is passing an unordered map of strings, the resulting code should compile. 为了匹配调用者传递无序的字符串映射这一事实,生成的代码应该编译。

What's happening inside your bar() is a separate issue. 你的bar()里面发生了什么bar()是一个单独的问题。 Using the static_cast answers the question of how to get the candidate template bar recognized. 使用static_cast回答了如何识别候选模板bar

Sam makes a good observation about how U is inconsistent in bar . Sam很好地观察了Ubar是如何不一致的。 But in your simple example, why go through all the trouble of const std::function<void (std::unordered_map<int, T>&&)>& when you could write: 但是在你的简单例子中,为什么要经历const std::function<void (std::unordered_map<int, T>&&)>&所有麻烦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) {
  });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C ++-为什么忽略带有函数指针参数的候选模板? - C++ - Why is this candidate template with a function pointer parameter ignored? “候选模板被忽略:无法匹配......”用于模板函数的模板函数参数 - "candidate template ignored: could not match ..." for template function argument to template function C ++:候选模板被忽略:模板参数的显式指定参数无效 - C++: candidate template ignored: invalid explicitly-specified argument for template parameter C++ lambda as std::function 在模板 ZC1C425268E68385D1AB5074C14 - C++ lambda as std::function in template function 将std :: string作为函数参数传递时的C ++类型转换 - C++ typecasting when passing std::string as function argument 在 C++ 中将 Lambda 表达式传递给 std::function - Passing a Lambda Expression to std::function in C++ C ++ lambda转换 - 为什么候选构造函数不可行:没有已知的从lambda到std :: function的转换 - C++ lambda conversion — why is candidate constructor not viable: no known conversion from lambda to std::function C ++ lambda表达式作为函数模板中的参数 - C++ lambda expression as an argument in function template 在 C++ 中将 function 模板作为 function 参数传递 - Passing a function template as a function argument in C++ 在 C++ 模板中将类型传递给 Lambda 函数 - Passing Type Into Lambda Function In C++ Template
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM