【问题标题】:Return type of a C++ lambdaC++ lambda 的返回类型
【发布时间】:2014-02-23 03:19:35
【问题描述】:

我正在编写一个模板函数,它以函数对象(现在是 lambda)作为参数,以 lambda 数据类型作为模板参数,并返回与 lambda 返回相同的类型。像这样:

template<typename TFunctor, typename TReturn>
TReturn MyFunc(TFunctor &Func, TReturn) //The second arg is just to keep the template spec happy
{
    return Func();
}

消费代码是这样的:

int n = MyFunc([](){return 17;}, int());

我不喜欢指定返回数据类型的丑陋方式。编译器生成的 lambda 类中是否有一些内置的 typedef 可以给我它的返回类型?这样 MyFunc 就可以像这样运行:

template<typename TFunctor>
TFunctor::return_type MyFunc(TFunctor &Func)
{ //...

我希望它返回与 lambda 返回相同的类型,而无需明确说明该类型。

编辑:目前,我所关心的所有 lambda 表达式都是无争议的。变量捕获也能做到这一点。

【问题讨论】:

  • 根据TFunctor 的实际情况,它可能有一个重载的operator(),这意味着返回类型可以取决于你给它的参数。 (不过,对于非泛型 lambda,情况并非如此)
  • @leemes 对于泛型 lambda,尚未为真。随着向 C++1y 引入多态 lambda,这种情况将会改变。
  • @Nevin 这就是为什么我说“对于 non-generic lambdas 来说不是这样”,这意味着它们的返回类型是固定的/已知的,无需查看参数。使用通用 lambda 会改变这种情况。泛型 lambda can(但不是必须)的返回类型取决于其参数。当您说“多态 lambda”时,您是指 C++14 中的通用 lambda 吗?

标签: c++ c++11 lambda


【解决方案1】:

由于返回类型可能取决于给定函子的参数,因此您需要在某处指定它们以查询返回类型。因此,当谈到泛型函子(不限于(非泛型)lambdas)时,在不知道参数类型的情况下无法确定返回类型。

C++11 有关键字decltype,它可以与尾随返回类型一起使用,以便通过命名一个依赖于函数参数(这里取决于Func 是什么):

template<typename TFunctor>
auto MyFunc(TFunctor &Func) -> decltype(Func(/* some arguments */))
{ ... }

因此,例如,如果您要在没有参数的情况下调用它(我在查看您的 lambda 示例时假设是这样),只需编写:

template<typename TFunctor>
auto MyFunc(TFunctor &Func) -> decltype(Func())
{ 
    return Func();
}

在 C++14 中,你甚至可以完全省略返回类型而直接编写

template<typename TFunctor>
auto MyFunc(TFunctor &Func)
{ 
    return Func();
}

请注意,即使在 C++03 中,您也不必提供另一个函数参数;另一个模板参数就足够了:

template<typename TReturn, typename TFunctor>
TReturn MyFunc(TFunctor &Func)
{
    return Func();
}

int n = MyFunc<int>(someFunctorReturningAnInt);

【讨论】:

    【解决方案2】:

    @leemes 的回答很好,但作为奖励,你可以使用自 C++17 以来内置的std::invoke_result_t

    #include <type_traits>
    #include <iostream>
     
    struct S {
        double operator()(char, int&);
        float operator()(int) { return 1.0;}
    };
          
    int main()
    {   
        // std::invoke_result uses different syntax (no parentheses)
        std::invoke_result<S,char,int&>::type b = 3.14;
        static_assert(std::is_same<decltype(b), double>::value, "");
    }
     
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-28
      • 1970-01-01
      • 2012-03-26
      • 1970-01-01
      • 1970-01-01
      • 2012-09-20
      相关资源
      最近更新 更多