【问题标题】:How to return lambda pointer in a template?如何在模板中返回 lambda 指针?
【发布时间】:2013-11-24 22:54:58
【问题描述】:

我必须创建一个模板,其返回值是指向某个 lambda 函数的指针(由模板参数确定)。

编译器反馈:

error: no matching function for call to ‘laptr(int)’

代码有什么问题?如何解决问题?

#include <iostream>

using namespace std;

template <typename T>
T laptr(int par);

int main(){
    laptr(1);
    return 0;
}

///////////

template <typename T>
T laptr(int par)
{
    if (par == 1)
    {
        int p1 = [](int a, int b)->int{return a*b; };
        return p1;
    }
    else
    {
        double p2 = [](double a, double b)->double{return a + b; };
        return p2;
    }
}

【问题讨论】:

  • 编译器在调用laptr方法时无法推断返回类型。
  • 函数模板的模板参数只能从它的常规实参推导出来,而不是从它的主体推导出来。由于从不包含T的参数中永远无法推导出T,所以这个模板只能称为laptr&lt;sometype&gt;(value),这显然是没有用的。
  • 此外,您似乎正在尝试根据参数的值返回不同类型的 lambda。您的语法不正确,但这并不重要。这根本无法做到。模板不会神奇地使之成为可能。

标签: c++ templates pointers c++11 lambda


【解决方案1】:

您可以使用std::function 来存储 lambda 函数:

template <typename T>
std::function<T(T,T)> laptr (int par)
{
    if(par == 1)
        return [](T a, T b)->T {return a*b;};
    else
        return [](T a, T b)->T {return a+b;};
}

甚至是指向函数的指针

template <typename T>
auto laptr (int par) -> T(*)(T,T)
{
    ...
}

 

你可以这样使用它

auto func = laptr<double>(1);

auto result = func(8,2); // 8*2=16

【讨论】:

  • 如果 lambdas 不需要捕获任何东西,甚至是一个普通的旧函数指针。
【解决方案2】:

你的根本问题是:

template <typename T>

...这里,T 是/必须在编译时完全确定,但是:

T laptr(int par)

par 直到运行时才知道,并且:

if (par == 1)
{
    int p1 = [](int a, int b)->int{return a*b; };
    return p1;
}
else
{
    double p2 = [](double a, double b)->double{return a + b; };
    return p2;
}

在这里,T 直到您决定要执行 if 语句的哪一段后才能知道,因此类型 1) 必须在代码完成编译之前知道,更不用说执行的任何事情了,但是2) 在代码执行之前无法确定。

显然你不能同时发生这两种情况,因此代码无法编译。

有很多替代方案——指向函数的指针、std::functionCommand 对象(在现代 C++ 设计中定义)等等。所有这些都可以这项工作本质上类似:与其尝试返回每个 lambda 的精确类型,他们将定义一些可以保存任一 lambda 类型的通用类型,并返回该类型的对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 2011-08-02
    • 2020-12-24
    • 1970-01-01
    • 2013-12-05
    相关资源
    最近更新 更多