2015-06-11 12 views
8

Mam małą funkcję lambda, która odnajdzie i zwróci QTreeWidgetItem. Ale jeśli nie znajdzie danego przedmiotu, zwróci on nullptr. Ale jeśli spróbuję to skompilować, to powoduje to błąd.Jak zwrócić nullptr z funkcji lambda?

Funkcja:

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

Błąd:

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

Zmieniłem wspomniany wiersz z tego i teraz kompiluje:

return (QTreeWidgetItem*)(nullptr); 

ale chciałbym tego uniknąć składnia. Jak mogę to rozwiązać?

Używam Visual Studio 2012.

+0

To wygląda jak błąd w VS2012? – Yakk

+0

@Yakk: Dlaczego? Komunikat o błędzie jest całkiem jasny, prawda? – MSalters

+0

@MSalters Hmm. Dziwne, tak naprawdę uważałem, że tak długo, jak późniejsze typy powrotu są kompatybilne (domyślnie wymienialne) z pierwszym typem zwracania, wszystko było w porządku. – Yakk

Odpowiedz

11

Możesz dodać wyraźnie typ powrót adnotacji:

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

W ten sposób nullptr zostanie przekonwertowany na typ wskaźnika. Otrzymujesz ten błąd, ponieważ lambda zakłada, że ​​nie należy dokonywać konwersji i traktuje nullptr_t jako uzasadniony alternatywny typ zwrotu.


Zamiast tego należy rozważyć użycie (std::)optional. Niblability wskaźników można wykorzystać do reprezentowania brakującego zwrotu, ale nie oznacza to, że musi to być koniecznie.

+4

Nie zgadzam się z ostatnim punktem dotyczącym "opcjonalne": większość rzeczy w 'Qt' jest przekazywana przez wskaźniki i uważam, że wynik tej lambda jest przekazywany gdzieś do' Qt'. Lepiej jest też podążać za ich stylem, nawet jeśli może to być złe w nowoczesnym C++. – lisyarus

+1

@lisyarus Stąd * rozważ *.Nie musi to mieć sensu w tym konkretnym przykładzie, ale może być opcją dla innego czytelnika. –

+0

Rozważ usunięcie ostatniego komentarza dotyczącego używania 'std :: optional' zamiast zwracania nullptr. Nie sądzę, żeby to poprawiło twoją odpowiedź. Górna część jest po prostu idealna. –

2

Jeśli chcesz po prostu uniknąć składnię, zamiast odlewania, można to tak:

static_cast<QTreeWidgetItem*>(nullptr); 

Zrobiłem mały przykład, w jaki sposób Bartka i odpowiedź kopalni naprawdę działa:

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

Dlaczego * nie powinno * Twój przykład kompilować dobrze? Parametr struct może zostać pominięty całkowicie, pozostawiając lambdę, której typem powrotu jest * just * 'nullptr_t'. –

+0

Twoja odpowiedź jest znacznie lepsza @BartekBanachewicz. Usunięcie kopalni i udzielenie ci +1. – gsamaras

+0

Twoja uwaga 'static_cast' była jednak w porządku. –

Powiązane problemy