【问题标题】:invoke_result_t<> not matching lambda with a reference parameterinvoke_result_t<> 没有将 lambda 与引用参数匹配
【发布时间】:2019-02-09 07:14:26
【问题描述】:

当类型是右值引用或没有引用时,使用接受模板化函数的函数效果很好,但一旦我将其设为左值引用,它就会中断。

请注意,这里目前没有使用 V,但无论是否使用,它仍然无法编译。

using namespace std;

template <typename F, typename V = std::invoke_result_t<F, string>>
void func(F f) {
    std::vector<string> v = { "a", "b", "c" };
    std::for_each(v.begin(), v.end(), f);
}

int main() {
    func([](string s) { return s.length(); });         // Good
    // func([](string& s) { return s.length(); });     // Bad
    func([](const string& s) { return s.length(); });  // Good
}

main.cpp:在函数'int main()'中:

main.cpp:18:46: 错误:没有匹配函数调用 'func(main()::)'

 func([](string& s) { return s.length(); });

                                          ^

main.cpp:11:6: 注意:候选:'template void func(F)'

  void func(F f) {

       ^~~~

main.cpp:11:6: 注意:模板参数推导/替换失败:

我做不到

std::invoke_result_t<F, string&>

而我做不到

std::invoke_result_t<F, std::add_lvalue_reference_t<string>>

最后一个是在黑暗中拍摄的。我的模板知识不是很好。我一直在这里和各种博客/谷歌/等上搜索,但没有取得太大成功。

【问题讨论】:

  • 要捕获所有情况,您可以尝试使用std::invoke_result_t&lt;F, string const &amp;&gt;

标签: c++ templates c++17


【解决方案1】:
std::invoke_result_t<F, string>

这意味着传递F 一个string 右值。如果F 采用左值引用,则不能。

我做不到

 std::invoke_result_t<F, string&>

是的,你可以。如果您想知道使用非常量左值调用它的结果是什么,请执行此操作。

在您的示例代码中使用时,您将它传递给一个左值。 string&amp;&amp; 重载不起作用。

【讨论】:

  • 我怎样才能让它接受任何功能?现在,如果我执行stringstring&amp;string&amp;&amp; 它会更改可以给出的lambda 类型,但我希望它能够支持任何类型。是否有可能让所有这些都被一个函数接受?我查看了 STL 的示例,但我不明白为什么它有效,但我的却没有。
  • @Water 你打算如何调用你传入的函数?很少有方法可以同时允许string&amp;&amp;string&amp; 参数调用函数,其中几乎所有这些都是无稽之谈。我不知道曾经接受两者的完整 STL 实现。 string&amp;&amp; 应该绑定到右值,string&amp; 绑定到左值,并且参数不应该两者兼有。
  • 我正在尝试实现我自己的std::for_each 作为学习练习,所以我希望它可以被任何东西调用,因为用户可以传递一个允许仅通过左值进行突变的 lambda,或使用 const 左值引用的函数,因此它们在循环期间不会发生任何复制,但确实想要修改它,或者如果用户愿意,甚至可以按值进行修改。 STL 接受任何类型的函数的示例,包括非常量左值引用:coliru.stacked-crooked.com/a/84951914356ed003(而我的在我执行左值引用时停止工作)。我错过了什么吗?
  • @Water 您的示例代码不接受int&amp;&amp;。您甚至注释掉了您尝试将其传入的行。这与您这样做时发生的情况相匹配...正是我所说的在我的回答中。所以我完全困惑什么让你感到困惑。 “任何东西”要么含糊不清,要么是谎言:你想让你的函数被你在邻居院子里看到的一只鸡调用吗?可能不是。大概您将编写调用该函数的代码。你错过了什么:你将如何调用你传入的函数?你错过了一个答案。
  • 放置一个右值引用对我来说是个坏主意,因为我不打算使用任何右值,但我仍然希望它接受它(如果失败,然后向用户抱怨)。但是,正如我在我的 OP 中想要的那样,我希望能够将 lambda 传递给一个适用于左值引用、const 左值引用或只是一个常规值的函数。 std::for_each 让它以某种方式工作,所以我做错了标准库没有做的事情。关于它的调用方式:我没有调用它,我将它传递给调用它的std:: 库函数(例如:for_each)。
猜你喜欢
  • 2023-01-10
  • 2021-06-28
  • 2012-08-08
  • 1970-01-01
  • 2021-09-26
  • 1970-01-01
  • 1970-01-01
  • 2022-06-14
  • 2013-10-22
相关资源
最近更新 更多