Lambda mit return void function?

Gast #6600341
Lesenswert?

wiso darf ich Lambdas return mit void machen?

clang, gcc und VS2017/19 sage das ist ok und explodieren dann beim 
Aufruf

was ist das tiefere Sinn dahinter?
1
void blub(){}
2

3
int main()
4
{
5
    auto x = []()
6
    { 
7
      // das erlaubt der Kompiler???
8
      return blub(); 
9
    };
10

11
    // das erlaubt der Kompiler nicht, völlig klar
12
    //return blub(); 
13

14
    return 0;
15
}

Cpp Insights (https://cppinsights.io/) macht das draus:
warum stört sich der Kompiler hier nicht an den return blub()s?
1
void blub(){}
2

3
int main()
4
{
5
  class __lambda_5_14
6
  {
7
    public: 
8
    inline /*constexpr */ void operator()() const
9
    {
10
      return blub();
11
    }
12
    
13
    using retType_5_14 = void (*)();
14
    inline /*constexpr */ operator retType_5_14 () const noexcept
15
    {
16
      return __invoke;
17
    };
18
    
19
    private: 
20
    static inline void __invoke()
21
    {
22
      return blub();
23
    }
24
  };
25
  __lambda_5_14 x = __lambda_5_14{};
26
  return 0;
27
}
#6600357
Lesenswert?

cppbert schrieb:
> wiso darf ich Lambdas return mit void machen?

Das hat eigentlich nichts mit Lambdas zu tun.

> clang, gcc und VS2017/19 sage das ist ok und explodieren dann beim
> Aufruf
>
> was ist das tiefere Sinn dahinter?

Der Sinn sind Templates. Es kann den Fall geben, dass man ein Template 
schreiben will, das eine Funktion aufruft, und was immer die zurückgibt, 
soll weitergegeben werden. Ohne dieses Feature würde das für alle 
Rückgabetypen außer eben void funktionieren.
Gast #6600362
Lesenswert?

ah, ok der Fehler ist nicht das ich von void returne sondern das meine 
main ein int als return-wert hat

aber trotzdem - warum wird so was nicht verhindern?
ist das wegen Templates und auto damit man da keinen Sonderweg gehen 
muss?
#6600395
Lesenswert?

cppbert schrieb:
> aber trotzdem - warum wird so was nicht verhindern?

Diese Möglichkeit wurde ganz bewusst hinzugefügt, um eben in Templates 
nicht unterscheiden zu müssen zwischen Funktionen, die void 
zurückliefern und Funktionen, die etwas andres zurückliefern.
Um mal dein Beispiel aufzugreifen:
1
void blub(){}
2
int  blah(){return 0;}
3

4
template<typename Ret>
5
struct X
6
{
7
    Ret test() { return func(); }
8
    Ret (*func)();
9
};
10

11
int main()
12
{
13
    X<void> a { blub };
14
    X<int> b { blah };
15
    
16
    a.test();
17
    return b.test();
18
}

Das würde ohne diese Möglichkeit nicht funktionieren. Man müsste extra 
eine Template-Spezialisierung der Klasse schreiben, nur um im Falle von 
Ret=void das return in test() wegzulassen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren