【问题标题】:C++: Passing a lambda as a function with template arguments makes deducing the template types failC++:将 lambda 作为带有模板参数的函数传递会使推导模板类型失败
【发布时间】:2020-01-15 23:21:32
【问题描述】:

在作为参数(作为 std::function 或作为函数指针)传递的函数的参数中使用模板类型会使编译器在函数作为 lambda 传递时无法推断类型(参见下面的代码) .有趣的是,如果函数不是 lambda,则此方法有效。

有什么方法可以实现吗?我已经在 Visual Studio 2017 和 GCC 7.4 中尝试了以下代码,但都失败了,所以它不太可能是编译器错误,并且可能有这种行为的原因。

#include <iostream>
#include <functional>

template <typename T>
void collide(void (*callback)(T)) // or std::function<void(T)> callback
{
    callback(42);
}

int main() {
    // doesn't compile: "could not deduce template arguments"
    collide([](int a) {
        std::cout << a << std::endl;
    });
}

【问题讨论】:

  • 这能回答你的问题吗? I cannot pass lambda as std::function - 函数指针和 lambda 也是如此。虽然它们有时可以转换为函数指针,但潜在的转换不能与模板匹配一起使用。
  • 是的,这似乎是相同的情况,尽管我的问题更笼统,因为它包含函数指针。关于这个问题的建议(转换为 std::function 然后传递)似乎有效,尽管我想知道为什么编译器不能为我这样做。
  • "它包括函数指针" - 因此我对函数指针的评论 - lambda 是 not 函数指针。它们有时可以转换为函数指针,但规则是在匹配template 时不允许转换。这些是规则。它们确实有意义,可以防止您在其他地方意外破坏 很多 东西,但遗憾的是,编译器不能在此处“为您执行此操作”。
  • 不知道“与模板匹配时不允许转换”。那就解释了,谢谢:)

标签: c++ c++11 visual-c++


【解决方案1】:

尝试使用以下调用

collide( *[](int a) {
    std::cout << a << std::endl;
});

将 lambda 显式转换为指向函数的指针。

这是一个演示程序。

#include <iostream>

template <typename T>
void f( void ( *fn )( T ) )
{
    fn( 42 );
}

void g( int x )
{
    std::cout << "g( " << x << " );\n";
}

int main()
{
    f( g );
    f( *[]( int x ) { std::cout << "main::lambda( " << x << ");\n"; } );
}

它的输出是

g( 42 );
main::lambda( 42);

【讨论】:

  • 这会导致 Visual Studio 2017 中的 'operator *' is ambiguous
  • 虽然它在 GCC 7.4 中工作。这更有趣!
  • 在 VS 上似乎是模棱两可的,因为它可以使用不同的调用约定转换为指针。在此处查看说明:devblogs.microsoft.com/oldnewthing/20150220-00/?p=44623
  • 无论如何,接受您的回答,因为它至少在 GCC 上有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-01
  • 2018-12-28
  • 2017-06-14
  • 2018-02-28
  • 2020-07-09
相关资源
最近更新 更多