Seite 27 von 69

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 15:37
von dot
Wo Cat im anderen Thread schon so fleißig am proposen war: Man bräuchte sowas wie storage class Qualifier für Pointer, damit diese nur an Adressen von Objekten von z.B. static storage duration binden können:

Code: Alles auswählen

const char* static blub = "abc";  // OK
const char* blab = blub;  // OK
const char* static blob = blab;  // error
Dann wäre es sicher, so einen Pointer aufzuheben, ohne den String kopieren zu müssen. Damit ließe sich wohl auch das Requirement an template non-type arguments von Pointertyp formalisieren...

EDIT: Wobei das im konkreten Fall wohl auch nur ein etwas besserer Ersatz für das ATOM wär...

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 16:40
von CodingCat
Richtig, sowas bräuchte man nicht nur hier. Ich bin auch schon am überlegen, wie man permanente Zeiger und temporäre Zeiger allgemeiner formalisieren könnte. Sehr häufig gibt man Zeiger (Referenzen) auf Stack-Objekte weiter, die mit der Zerstörung des jeweiligen Stack-Objekts ungültig werden. Das ist i.d.R. auch überhaupt kein Problem, weil zuvor alle Unteraufrufe wieder vom Stack verschwinden. Diese Zeiger dürfen nur auf keinen Fall permanent gespeichert werden:

Code: Alles auswählen

void foo()
{
   char name[] = "foo";
   use(name); // OK
   store(name); // error: object lifetime too short
   store("foo"); // OK
}

const char *storedName;

void use(const char *name)
{
   storedName = name; // error: object lifetime unspecified
}

void store(const char *extern name)
{
   storedName = name; // OK
}

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 16:53
von dot
CodingCat hat geschrieben:Richtig, sowas bräuchte man nicht nur hier. Ich bin auch schon am überlegen, wie man permanente Zeiger und temporäre Zeiger allgemeiner formalisieren könnte. Sehr häufig gibt man Zeiger (Referenzen) auf Stack-Objekte weiter, die mit der Zerstörung des jeweiligen Stack-Objekts ungültig werden. Das ist i.d.R. auch überhaupt kein Problem, weil zuvor alle Unteraufrufe wieder vom Stack verschwinden.
Um das zu verhindern, bräuchte man wohl relativ interessantes Verhalten, nämlich dass ein Pointer auf ein Objekt mit local automatic storage nur in einen Pointer der selbst local automatic storage duration hat gespeichert werden kann. Sowas wie cv qualifier, nur dass diese Qualifier mehr oder weniger über eine Ebene an Indirektion hinweg interagieren würden (der top-level local Qualifier ist für lokale Variablen implizit):

Code: Alles auswählen

local int x;  // OK
local int* local px = &x;  // OK
int** blub = new int*;
*blub = &px;  // error
Das Problem ist wohl nur, dass das so ziemlich 99.99999% aller vorhandenen C++ Programme breaken würde...

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 16:54
von CodingCat
dot hat geschrieben:Um das zu verhindern, bräuchte man wohl relativ interessantes Verhalten, nämlich dass ein Pointer auf ein Objekt mit local automatic storage nur in einen Pointer der selbst local automatic storage duration hat gespeichert werden kann. Sowas wie cv qualifier, nur dass diese Qualifier mehr oder weniger über eine Ebenen hinweg interagieren würden (der top-level local Qualifier ist für lokale Variablen implizit):
[...]
Das Problem ist wohl nur, dass das so ziemlich 99.99999% aller vorhandenen C++ Programme breaken würde...
Ganz genau. Und ganz genau, deshalb liegt dieses Proposal bei dem anderen, das ebenfalls 99.99999% aller vorhandenen C++ Programme zerstören würde; auf Halde.

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 16:56
von dot
Wobei es nur ein Syntaxproblem wäre. Wenn man den second level local Qualifier für lokale Variablen auch implizit machen würde, würde es wohl funktionieren, da jedes Programm das dann nicht mehr kompiliert wohl sowieso schon immer undefiniert war...

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 17:00
von CodingCat
Das Problem ist, sobald es implizit funktioniert, vergisst man, es richtig zu machen. Genau wie bei const-Correctness.

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 17:03
von dot
War auch Blödsinn, man bräuchte sowas wie auto, das den richtigen Qualifier vom rechten Typ inferiert, denn sonst könnte man keine lokalen Pointer auf nichtlokale Objekte mehr machen. Vielleicht bräuchte man gar kein eigenes local Keyword (welches in jedem Fall kontextsensitiv sein könnte), sondern könnte sogar auto verwenden:

Code: Alles auswählen

void f()
{
  int x;
  int* px = &x;  // px is implicitly declared int auto* px, deduced to int local* px
  int** blub = new int*;  // blub is implicitly declared int * auto * blub, deduced to int * dynamic * blub
  *blub = px;  // error: px is of type int local*, *blub is of type int dynamic*
}
Der dynamic und static Qualifier darf implizit wegkonvertiert werden, local dagegen nicht:

Code: Alles auswählen

void f()
{
  static int x;
  int* x = new int;  // OK, new int returns int dynamic*, can be converted to int*
  int* y = &x;  // OK, &x is int static*, can be converted to int*

  int a;
  int* z = &a;  // error, can't convert int local* to int*
}
Edit: Verdammt, wenn man im ersten Beispiel aber *blub an px zuweisen will, gehts wieder nicht...

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 17:30
von CodingCat
Ja, das wäre eventuell sinnvoll. Wobei ich local lokal ohnehin zum impliziten Standardfall machen würde, andernfalls wird das ganze vermutlich unbenutzbar. Das Verhalten unterscheidet sich auf jeden Fall stark von const-Transitivität:

Code: Alles auswählen

struct A
{
   int *p;
};

A g; // g global => p hat Typ int *extern

void foo()
{
   int i;
   A a; // a lokal => p hat Typ int *local
   a.p = &i; // OK
   foo(a); // OK

   g.p = &i; // error
   foo(g); // OK

   A &r = a; // Referenz lokal
   r.p = &i; // OK
   foo(r); // OK

   extern A b; // b extern => p hat Typ int *extern
   b.p = &i; // error
   foo(b); // OK
}

void bar(A &a)
{
   int j;
   a.p = &j; // error: _Parameter_-Referenz auf a NICHT mehr lokal => p hat Typ int *extern?!
   int *p = a.p; // error: p hat Typ int *local?! 
   // a.p hat einen Zwischentyp, nämlich Referenz auf externes int*local, also int *extern local
}
Klar ist das ein Problem bezüglich Abwärtskompatibilität. Aber möglicherweise ist es ohnehin Zeit für einen Modern-C++-Namespace?

Nachtrag: Die Lösung über die externe Referenz funktioniert nicht, es braucht wohl tatsächlich einen dritten Mischtypen extern local. :mrgreen:

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 17:46
von dot
Nach ein bisschen nachdenken glaub ich jetzt mal: Rein mit deduzieren von statischen Typen wird's nicht gehn, aber man könnte wohl auto verwenden, um sowas wie dieses inout aus D zu machen, nur für storage class Qualifier (und zugleich wohl auch für cv Qualifier!?)...

Code: Alles auswählen

int* g;

void f()
{
  int x;
  int** y = new int*;  // OK, int* auto* can be assigned int* dynamic*
  int* px = &x;  // OK, int auto* can be assigned int local*
  *y = &x;  // error, int* can't be assigned int local*
  *y = px;  // error, int* can't be assigned int auto*
  px = *y;  // OK, int auto* can be assigned int*
  g = px;  // error, int* can't be assigned int auto*
  px = g;  // OK, int auto* can be assigned int*
}

// second level auto is implicitly declared on local variables, top level auto/storage class qualifier is ignored just like with function signatures

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 18:18
von CodingCat
Ich verstehe noch nicht ganz, wozu du hier Deduktion brauchst. Ist das Ziel nicht gerade, Sicherheit durch wohldefinierte Konvertierungsregeln zu schaffen?

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 18:34
von dot
Das auto hier ist keine Deduktion, die Idee musste ich gleich wieder verwerfen, sondern ein neuer Qualifier. Die entsprechenden Konvertierungsregeln erlauben, dass ein auto Qualifier hinzugefügt wird und ein anderer storage class Qualifier zu auto degeneriert, aber niemals ein auto storage class Qualifier entfernt wird. Ein int* kann also in ein int auto* konvertiert werden, ein int local* kann zu einem int auto* konvertiert werden, ein int static* kann zu einem int auto* konvertiert werden, aber ein int auto* kann nicht zu einem int* konvertiert werden...

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 19:06
von CodingCat
Hm, ich kann dir leider nicht folgen, insbesondere wenn ich deinen Code mit dem geschriebenen vergleiche. Außerdem kann ich aus deinen Regeln gerade die Bedeutung von auto nicht ableiten. Eventuell sollten wir uns mal auf aussagekräftige Qualifiziernamen einigen, die insbesondere auch den impliziten Fall (kein Qualifizier) sinnvoll benennen.

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 19:19
von dot
Ok, verwenden wir statt auto einfach local, einer der beiden ist in meinem obigen Modell eigentlich sowieso überflüssig. Folgende Regeln:
  • top level local (T local bzw. local T) ist bei lokalen Objekten implizit.
  • top level static ist bei Objekten mit static storage duration implizit.
  • top level storage qualifier wird ansonsten ignoriert (wie z.B. cv qualifier bei Funktionssignaturen auch).
  • second level local (T local* bzw. local T*) kann durch Konvertierung hinzugefügt werden.
  • second level local ist bei lokalen Objekten implizit.
  • static kann durch Konvertierung hinzugefügt, entfernt oder zu local werden.

Code: Alles auswählen

int* g;
int** h = &g;  // OK, int* static* can be converted to int**

void f()
{
  int x;
  int* px = &x;  // OK, no conversion necessary
  int** y = new int*;  // OK, int** can be converted to int* local*
  *y = &x;  // error, int local* can't be converted to int*
  *y = px;  // error, int local* can't be converted to int*
  px = *y;  // OK, int* can be converted to int local*
  g = px;  // error, int local* can't be converted to int static*
  px = g;  // OK, int static* can be converted to int local*
  *y = g;  // OK, no conversion necessary
  y = &g;  // OK, int* static* can be converted to int* local*
  g = *y;  // OK, int* can be converted to int static*
}
Edit: Verdammt, bei h = y geht's wieder kaputt...

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 19:36
von CodingCat
Okay, jetzt fällt mir schonmal auf, dass ich meine Qualifizier vorhin die ganze Zeit versehentlich auf die falsche Seite des Zeigertypkonstruktors geschrieben hatte. Davon abgesehen haben wir denke ich den gleichen Grundregelsatz.

Interessant wird jetzt die Parameterübergabe, siehe oben. Eigentlich sollten Zeiger-Parameter nach den gleichen Regeln implizit local sein. Dann geht jedoch sämtlicher alter Code kaputt.

Obendrein das Referenzbeispiel von oben. Eine veränderliche Parameter-Referenz eines local Zeigers der aufrufenden (Ober-)Funktion ist kein reines Alias für diesen Zeiger, denn sonst könnten wir in dem Zeiger lokale Objekte der Unterfunktion speichern. Sie ist jedoch auch kein Alias für einen nicht-lokalen Zeiger, denn sonst könnten wir lokale Objekte der Oberfunktion in der Unterfunktion einfach so über den Aufruf hinaus referenzieren. Deshalb mein Hinweis zu einem Mischtypen local extern:
  • extern erlaubt Neubeschreibung des Zeigers mit nicht-lokalen Objekten und verbietet Neubeschreibung mit local-Objekten
  • local erlaubt Lesen/Nutzung des Zeigers ohne permanente Speicherung und verbietet Lesen für extern-Speicherung
Standardmäßig schließen sich die Qualifizier aus, d.h. bei expliziter Angabe des einen verschwindet der andere. Es sei denn, beide werden explizit angegeben oder es handelt sich um referenzierende Parameter. Bei Parametern sollten veränderliche Referenzierungen automatisch transitiv eine Ergänzung um extern nach sich ziehen, ohne jedoch implizites local zu entfernen.

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 19:50
von dot
Ja, ich bin grad draufgekommen, dass ich da vorhin sowieso komplett verwirrt war (kommt vor). Mit Zeigern gibt's da rein prinzipiell wohl ein Problem, da diese beliebig zugewiesen werden können, mit Referenzen allein könnte ein Ansatz der den storage Qualifier deduziert oder so aber funktionieren. Nur is das dann halt irgendwie schon wieder fast sinnlos...

Re: Anti-Jammer-Thread

Verfasst: 04.11.2012, 21:45
von CodingCat
Datenorientierung hat einige Vorzüge. Einer ist das großartige Zusammenspiel mit range-based for:

Code: Alles auswählen

for (auto &&material : controller.Mesh->GetMaterials())
    for (auto &&technique : material->GetTechniques())
        for (auto &&pass : technique.EffectDriver->GetPasses())
        {
        }
Um lineare Ranges von polymorphen Typen anbieten zu können, habe ich gerade einen strided_ptr eingeführt.

Re: Anti-Jammer-Thread

Verfasst: 07.11.2012, 19:56
von CodingCat

Re: Anti-Jammer-Thread

Verfasst: 08.11.2012, 01:02
von Lurnon
Aktuelles Projekt (Kundenanalysesoftware für eine Physiotherapie) erfolgreich abgeschlossen. Endlich Zeit meine BA weiter zu schreiben :D

Re: Anti-Jammer-Thread

Verfasst: 08.11.2012, 06:31
von RazorX
CodingCat hat geschrieben:Die Productivity Power Tools 2012 sind da!
Jawoll!

Re: Anti-Jammer-Thread

Verfasst: 09.11.2012, 12:49
von CodingCat
Ich habe soeben mein erstes C++ Language Proposal gepostet: More Uniform Initialization in Constructors

Re: Anti-Jammer-Thread

Verfasst: 10.11.2012, 15:32
von eXile
CodingCat hat geschrieben:Ich habe soeben mein erstes C++ Language Proposal gepostet: More Uniform Initialization in Constructors
Bin ich der einzige, der eigentlich nur ein einziges return; in jedem seiner Konstruktoren haben möchte? Da hat man eine wohldefinierte Initialisierungsreihenfolge (in der Reihenfolge aus der Klassendeklaration), vermeidet Kopien und ich kann auch sonst keinen wirklichen Nachteil erkennen.

Re: Anti-Jammer-Thread

Verfasst: 10.11.2012, 19:14
von CodingCat
eXile hat geschrieben:Bin ich der einzige, der eigentlich nur ein einziges return; in jedem seiner Konstruktoren haben möchte? Da hat man eine wohldefinierte Initialisierungsreihenfolge (in der Reihenfolge aus der Klassendeklaration), vermeidet Kopien und ich kann auch sonst keinen wirklichen Nachteil erkennen.
Verstehe ich nicht. Hast du in deinem Konstruktor nur das return? Wieso überhaupt im Konstruktor ein return? Inwiefern löst das Probleme mit der Initialisierungsreihenfolge oder mit temporären Variablen? Wie kommst du bei komplexer Initialisierung ohne Kopie/Move aus?

Re: Anti-Jammer-Thread

Verfasst: 10.11.2012, 23:09
von Krishty
Ich habe gerade aus purer Prokrastination alle Warnungen eingeschaltet und dabei tatsächlich einen Fall von ungewollter unsigned infection entdeckt.

Re: Anti-Jammer-Thread

Verfasst: 11.11.2012, 16:46
von Artificial Mind
Assimp in mein Projekt integriert, endlich vernünftig Tangenten aus .obj Dateien :)

Re: Anti-Jammer-Thread

Verfasst: 12.11.2012, 12:57
von joggel
Ich hab ein tolles neues Avatar :geek:

Re: Anti-Jammer-Thread

Verfasst: 12.11.2012, 13:37
von Biolunar
joggel hat geschrieben:Ich hab ein tolles neues Avatar :geek:
Tard :D

Re: Anti-Jammer-Thread

Verfasst: 12.11.2012, 17:51
von Chromanoid
Apropos @CodingCat, die Katze sieht nicht gesund um nicht zu sagen angefahren aus :shock: ;)

Re: Anti-Jammer-Thread

Verfasst: 12.11.2012, 19:15
von CodingCat
Chromanoid hat geschrieben:Apropos @CodingCat, die Katze sieht nicht gesund um nicht zu sagen angefahren aus :shock: ;)
Ach was, der kugelt sich wohlig auf dem Boden. Wenn man den Tabellen glauben darf, war er da aber umgerechnet schon 84, nach einem derart langen Leben auf der Straße muss er also nicht mehr jugendlich aussehen. ;) Er ist btw. derselbe wie auf dem alten Avatar, ich dachte ich mache mal ein Upgrade bezüglich Bildmaße, weil mir das Foto gerade aus einem Directory entgegenhüpfte.

Re: Anti-Jammer-Thread

Verfasst: 14.11.2012, 12:46
von joggel
Kommt... wir spielen alle "Drückt Dich total behindert aus, und such den Fehler bei den Anderen" :lol:
Mir war einfach mal so... bin urlaubsreif ^^

Re: Anti-Jammer-Thread

Verfasst: 15.11.2012, 10:04
von joggel
Anscheinend ist dieses QtQuick3D doch garnicht sooo scheisse..