p.i.g.
p.i.g.

Reputation: 2995

How to return nullptr from a lambda function?

I have a small lambda function which shall find and return a QTreeWidgetItem. But if it does not find the given item, then it shall return a nullptr. But if I try to compile it then it gives me an error.

The function:

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.
};

The error:

Error 1 error C3487: 'nullptr': all return expressions in a lambda must have the same type: previously it was 'QTreeWidgetItem *' cpp 251

I changed the mentioned line with this and now it compiles:

return (QTreeWidgetItem*)( nullptr );

but I would like to avoid this syntax. How can I solve this ?

I use Visual Studio 2012.

Upvotes: 13

Views: 3216

Answers (3)

Pato Sanda&#241;a
Pato Sanda&#241;a

Reputation: 659

I had this very same issue with some Smart Pointers, so I found I could do this to avoid the issue:

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

Similarly, for shared pointer, just repleace MyPointer* by std::shared_ptr<MyPointer>.

So your code would looks like:

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;
};

Upvotes: 0

Bartek Banachewicz
Bartek Banachewicz

Reputation: 39390

You can add an explicit return type annotation:

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

That way nullptr will be converted to your pointer type properly. You're getting that error because the lambda assumes no conversions should be made, and treats nullptr_t as a legitimate alternative return type.


As a side note, consider using (std::)optional instead. The nullability of pointers can be used to represent a missing return, but it doesn't mean it necessarily should be.

Upvotes: 19

gsamaras
gsamaras

Reputation: 73394

If you just want to avoid the syntax, rather than the casting, you could it like this:

static_cast<QTreeWidgetItem*>(nullptr);

I made a small example, on how Bartek's and mine's answer really work:

#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;
}

Upvotes: 4

Related Questions