Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.net  
   

Die mobilen Seiten von c++.net:
https://m.c-plusplus.net

  
C++ Forum :: C++ (alle ISO-Standards) ::  Ist goto xy wirklich so böse?  
Gehen Sie zu Seite Zurück  1, 2, 3, 4, 5  Weiter
  Zeige alle Beiträge auf einer Seite
Auf Beitrag antworten
Autor Nachricht
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 23750
Beitrag hustbaer Mitglied 21:24:55 13.11.2017   Titel:              Zitieren

@Mechanics
Das wäre dann longjmp in Verkleidung, oder? (IIRC verwendet boost::context longjmp ...?)
Wäre interessant wie die Performance davon ist.

_________________
Until every person can enjoy all their human rights, we will not stop. I support Amnesty International. Will you?
https://www.amnesty.org / https://www.amnesty.de / https://www.amnesty.at
Mechanics
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.01.2012
Beiträge: 4142
Beitrag Mechanics Mitglied 23:24:00 13.11.2017   Titel:              Zitieren

So in der Art...
HarteWare
Mitglied

Benutzerprofil
Anmeldungsdatum: 16.02.2013
Beiträge: 460
Beitrag HarteWare Mitglied 00:31:48 14.11.2017   Titel:              Zitieren

Ich habe im Clang sourcecode auch ein goto gesehen, es wurde verwendet, um rekursive Funktionsaufrufe zu verhindern (goto wird an mehreren Stellen verwendet, aber wofür weiß ich nicht überall, wohl teilweise auch um code zu überspringen).

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
/// LexTokenInternal - This implements a simple C family lexer.  It is an
/// extremely performance critical piece of code.  This assumes that the buffer
/// has a null character at the end of the file.  This returns a preprocessing
/// token, not a normal token, as such, it is an internal interface.  It assumes
/// that the Flags of result have been cleared before calling this.
bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) {
LexNextToken:
// ...
    // We know the lexer hasn't changed, so just try again with this lexer.
    // (We manually eliminate the tail call to avoid recursion.)
    goto LexNextToken;
// ...
}
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 23750
Beitrag hustbaer Mitglied 01:13:01 14.11.2017   Titel:              Zitieren

@HarteWare
Ich glaube dir dass du das dort so gesehen hast. Und vermutlich kann man argumentieren dass es mit dem goto irgendwie klarer wird oder schöner ist*. Ich würde das aber dennoch mit nem ganz normalen Loop ersetzen:

C++:
1
2
3
4
5
6
7
8
9
10
/// ...
bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) {
    while (true) {
    // ...
        // We know the lexer hasn't changed, so just try again with this lexer.
        // (We manually eliminate the tail call to avoid recursion.)
        continue; // Look ma, no goto!
    // ...
    }
}

Wenn das langsamer sein sollte als die goto-Version, dann läuft irgendwas extrem falsch.


*: Vielleicht ist das für Leute die gewohnt sind rekursive Parser zu schreiben pfui-spinne-hässlich, weil es wie ein Loop aussieht. Naja aber, Pech, Tail-Recursion ist nunmal das selbe wie ein Loop. :o)

_________________
Until every person can enjoy all their human rights, we will not stop. I support Amnesty International. Will you?
https://www.amnesty.org / https://www.amnesty.de / https://www.amnesty.at


Zuletzt bearbeitet von hustbaer am 02:14:59 14.11.2017, insgesamt 1-mal bearbeitet
happystudent
Mitglied

Benutzerprofil
Anmeldungsdatum: 10.10.2013
Beiträge: 804
Beitrag happystudent Mitglied 19:30:08 14.11.2017   Titel:              Zitieren

Mich würde vor allem eine saubere Möglichkeit für (geschachtelte) Lambdas interesieren...

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
 
template <typename Callback>
void my_for(size_t start, size_t end, Callback callback)
{
    for (size_t i = start; i < end; ++i) { callback(i); }
}
 
int main()
{
    my_for(0, 3, [](size_t i)
    {
        my_for(0, 3, [&i](size_t j)
        {
            if (i == 0 && j == 1)
                return; // Überspringt nur einen Durchgang
            std::cout << i << " " << j << "\n";
        });
    });
}


Momentan mache ich das mit throw obwohl das ja verpönt ist (und angeblich ja auch einen ziemlich hohen Overhead hat)... Sehe aber keine "schöne" Alternative?

Weil hier geht ja nichtmal was mit goto (nicht dass ich das dann schön finden würde).

Ich fände es eigentlich nicht schlecht wenn man throw ohne großen Overhead ganz "normal" verwenden könnte, nicht nur für Exceptions... Schließlich kann man auch nicht-Exception Objekte werfen.
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 23750
Beitrag hustbaer Mitglied 20:17:26 14.11.2017   Titel:              Zitieren

In diesem Fall easy, da die Lambdas keinen Returnwert haben:
C++:
1
2
3
4
5
6
7
8
template <typename Callback>
bool my_for(size_t start, size_t end, Callback callback)
{
    for (size_t i = start; i < end; ++i)
        if (!callback(i))
            return false;
    return true;
}


Lässt sich aber auch allgemein anwenden. In dem Fall dann halt z.B. über nen bool& stop Parameter oder indem man Tuples zurückgibt.

Oder auch, ganz anderer Ansatz: nich auf alles mit Lambdas draufhauen wo man mit irgendwas draufhauen kann.

_________________
Until every person can enjoy all their human rights, we will not stop. I support Amnesty International. Will you?
https://www.amnesty.org / https://www.amnesty.de / https://www.amnesty.at
Mechanics
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.01.2012
Beiträge: 4142
Beitrag Mechanics Mitglied 20:44:18 14.11.2017   Titel:              Zitieren

hustbaer schrieb:
Wäre interessant wie die Performance davon ist.


Ja, wär schon interessant, wenn mal jemand sowas ausprobiert ^^
Und nein, ich glaub nicht, dass die intern longjmp verwenden, das ist denk ich etwas komplizierter.
happystudent
Mitglied

Benutzerprofil
Anmeldungsdatum: 10.10.2013
Beiträge: 804
Beitrag happystudent Mitglied 21:27:06 14.11.2017   Titel:              Zitieren

hustbaer schrieb:
In diesem Fall easy, da die Lambdas keinen Returnwert haben:


Nee, das is nix, dann muss ich ja immer auch einen Wert in der Schleife zurückgeben auch wenn ich gar nicht breaken will.

hustbaer schrieb:
Lässt sich aber auch allgemein anwenden. In dem Fall dann halt z.B. über nen bool& stop Parameter oder indem man Tuples zurückgibt.


Du meinst z.B. so?

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
 
template <typename Callback>
void my_for(size_t start, size_t end, Callback callback)
{
    bool stop = false;
    for (size_t i = start; i < end; ++i) { callback(i, stop); if (stop) return; }
}
 
int main()
{
   
 
    my_for(0, 3, [](size_t i, bool &early_stop_1)
    {
        my_for(0, 3, [&i, &early_stop_1](size_t j, bool &early_stop_2)
        {
            if (i == 0 && j == 1)
            {
                early_stop_1 = true;
                early_stop_2 = true;
            }
            std::cout << i << " " << j << "\n";
        });
    });
}


Klar geht, ist dann halt mehr oder weniger das äquivalent zu Zustands-Variablen wenn man aus einer "normalen" verschachtelten Schleife breaken will. Schön find ichs halt nicht (wie bei "normalen" Schleifen eben auch).


hustbaer schrieb:
Oder auch, ganz anderer Ansatz: nich auf alles mit Lambdas draufhauen wo man mit irgendwas draufhauen kann.


Dafür sind die doch da, gerade bei so kleinem body? Also ich mag Lambdas :)


Zuletzt bearbeitet von happystudent am 21:27:48 14.11.2017, insgesamt 1-mal bearbeitet
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 23750
Beitrag hustbaer Mitglied 22:03:40 14.11.2017   Titel:              Zitieren

happystudent schrieb:
hustbaer schrieb:
In diesem Fall easy, da die Lambdas keinen Returnwert haben:


Nee, das is nix, dann muss ich ja immer auch einen Wert in der Schleife zurückgeben auch wenn ich gar nicht breaken will.

Nö, musst du nicht.
Du musst nur für zwei recht unterschiedliche Dinge, nämlich für die Variante die vorzeitigen Abbruch erlaubt und die die keinen vorzeitigen Abbruch erlaubt, zwei unterschiedliche Funktionen machen.

happystudent schrieb:
hustbaer schrieb:
Lässt sich aber auch allgemein anwenden. In dem Fall dann halt z.B. über nen bool& stop Parameter oder indem man Tuples zurückgibt.


Du meinst z.B. so?
(snip)

Klar geht, ist dann halt mehr oder weniger das äquivalent zu Zustands-Variablen wenn man aus einer "normalen" verschachtelten Schleife breaken will. Schön find ichs halt nicht (wie bei "normalen" Schleifen eben auch).

Ich meins in weniger hässlich und mit nur einer "stop" Variable für beide Schleifen.


happystudent schrieb:
hustbaer schrieb:
Oder auch, ganz anderer Ansatz: nich auf alles mit Lambdas draufhauen wo man mit irgendwas draufhauen kann.


Dafür sind die doch da, gerade bei so kleinem body? Also ich mag Lambdas :)

Ja, klar. Das schöne neue Werkzeug einfach mal für jede Aufgabe einsetzen, obwohl sich die Aufgabe mit Händen und Füssen dagegen wehrt, ist immer volle schlau.


ps:
happystudent schrieb:
C++:
    my_for(0, 3, [](size_t i)
    {
        my_for(0, 3, [&i](size_t j)
        {

&i
*facepalm*

_________________
Until every person can enjoy all their human rights, we will not stop. I support Amnesty International. Will you?
https://www.amnesty.org / https://www.amnesty.de / https://www.amnesty.at


Zuletzt bearbeitet von hustbaer am 22:08:21 14.11.2017, insgesamt 1-mal bearbeitet
happystudent
Mitglied

Benutzerprofil
Anmeldungsdatum: 10.10.2013
Beiträge: 804
Beitrag happystudent Mitglied 22:22:27 14.11.2017   Titel:              Zitieren

hustbaer schrieb:

Ja, klar. Das schöne neue Werkzeug einfach mal für jede Aufgabe einsetzen, obwohl sich die Aufgabe mit Händen und Füssen dagegen wehrt, ist immer volle schlau.


Weiß ja nicht wo du rausliest dass ich das für jede Aufgabe einsetze. :confused:

Nur so: Das war ein Minimalbeispiel. Ich ersetze nicht jede for-Schleife durch ein Lambda, falls du das dachtest.

Gerade beim Erstellen einer eigenen for Schleife wehrt sich die Aufgabe aber nicht "mit Händen und Füßen", sondern ist geradezu prädestiniert dafür, z.B. concurrency::parallel_for oder std::for_each.


hustbaer schrieb:

&i
*facepalm*


Äh, was ist daran auszusetzen? Wenn ich in der inneren Schleife auf i zugreifen können will muss ich es auch capturen.

Und da ich i, wie in einer normalen inneren for-Schleife ändern können will, capture by reference.

Wenn du hier schon facepalmst dann bitte mit Begründung, bin gespannt :)


Zuletzt bearbeitet von happystudent am 22:57:26 14.11.2017, insgesamt 2-mal bearbeitet
C++ Forum :: C++ (alle ISO-Standards) ::  Ist goto xy wirklich so böse?  
Gehen Sie zu Seite Zurück  1, 2, 3, 4, 5  Weiter
Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.net ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info und www.c-plusplus.net enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.