【问题标题】:How to return nullptr from a lambda function?如何从 lambda 函数返回 nullptr?
【发布时间】:2015-08-27 06:42:24
【问题描述】:

我有一个小的 lambda 函数,它可以找到并返回一个 QTreeWidgetItem。但是如果它没有找到给定的项目,那么它将返回一个nullptr。但是如果我尝试编译它,那么它会给我一个错误。

功能:

auto takeTopLevelItem = []( QTreeWidget* aTreeWidget, const QString& aText )
{
    const int count = aTreeWidget->topLevelItemCount();
    for ( int index = 0; index < count; ++index )
    {
        auto item = aTreeWidget->topLevelItem( index );
        if ( item->text( 0 ) == aText )
        {
            return aTreeWidget->takeTopLevelItem( index );
        }
    }
    return nullptr; // This causes a compilation error.
};

错误:

错误 1 ​​错误 C3487:'nullptr':lambda 中的所有返回表达式必须具有相同的类型:以前是 'QTreeWidgetItem *' cpp 251

我用这个改变了提到的行,现在它编译了:

return (QTreeWidgetItem*)( nullptr );

但我想避免这种语法。我该如何解决这个问题?

我使用Visual Studio 2012

【问题讨论】:

  • 这看起来像是 VS2012 中的错误?
  • @Yakk:为什么?错误信息很清楚,不是吗?
  • @MSalters 嗯。奇怪,我其实以为只要后面的返回类型与第一个返回类型兼容(隐式可转换),一切都很好。
  • IIRC C++11 的 lambda 提案是故意保守的。为了安全起见,省略了一些相当合理的扩展。

标签: c++11 lambda


【解决方案1】:

您可以添加显式返回类型注释:

auto takeTopLevelItem = []( ... ) -> QTreeWidgetItem*
{
    // ...
}

这样nullptr 将正确转换为您的指针类型。您收到该错误是因为 lambda 假定不应进行任何转换,并将 nullptr_t 视为合法的替代返回类型。


作为旁注,请考虑改用(std::)optional。指针的可空性可用于表示缺少返回,但这并不意味着它一定应该如此。

【讨论】:

  • 我不同意关于optional 的最后一点:Qt 中的大多数东西都是通过指针传递的,我相信这个 lambda 的结果会在某个地方传递给 Qt。此外,最好遵循他们的风格,即使它在现代 C++ 中可能是邪恶的。
  • @lisyarus 因此考虑。在这个特定的例子中它不一定有意义,但可能是其他读者的选择。
  • 考虑删除关于使用 std::optional 而不是返回 nullptr 的最后一条评论。我认为这不会使您的答案更好。顶部是完美的。
【解决方案2】:

如果你只是想避免语法,而不是强制转换,你可以这样:

static_cast<QTreeWidgetItem*>(nullptr);

我做了一个小例子,说明 Bartek 和我的答案如何真正起作用:

#include <iostream>

class A {
  int a;
};

auto bla = [] (A* obj, bool flag) -> A* {
  if(flag)
    return obj;
  return nullptr;
//  return static_cast<A*>(nullptr);
};

int main() {
  A obj;
  A* ptr = &obj;
  bool flag = false;
  if( bla(ptr, flag) == nullptr)
    std::cout << "ok\n";
  return 0;
}

【讨论】:

  • 为什么不应该你的例子编译得很好?可以完全省略参数结构,留下一个返回类型为 just nullptr_t. 的 lambda
  • 你的回答要好得多@BartekBanachewicz。删除我的并给你 +1。
  • 您的static_cast 评论非常好。
  • 嗯,你有什么建议?仅使用static_cast 编辑答案还是将其全部删除? @BartekBanachewicz
  • 我只留下static_cast 位(因为这里的代码示例显然不相关)。
【解决方案3】:

我对一些智能指针也有同样的问题,所以我发现我可以这样做来避免这个问题:

auto myFunc= [](MyClass* class)
{
    MyPointer* pointer = nullptr;
    
    if( class && class->isValid() )
    {
       pointer = class->getPointerInstance()
    }
    
    return pointer;
}

同样,对于共享指针,只需将 MyPointer* 替换为 std::shared_ptr&lt;MyPointer&gt;

所以你的代码看起来像:

auto takeTopLevelItem = []( QTreeWidget* aTreeWidget, const QString& aText )
{
  QTreeWidgetItem* item = nullptr;
  const int count = aTreeWidget->topLevelItemCount();
  for ( int index = 0; index < count; ++index )
  {
      auto item = aTreeWidget->topLevelItem( index );
      if ( item->text( 0 ) == aText )
      {
          item = aTreeWidget->takeTopLevelItem( index );
          break;
      }
  }
  return item;
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-17
    • 2019-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-25
    • 2017-10-29
    • 2016-08-15
    相关资源
    最近更新 更多