Anti-Jammer-Thread
Re: Anti-Jammer-Thread
Ja genau. Da gibt's auch das schöne Diagramm:

- dot
- Establishment
- Beiträge: 1748
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Anti-Jammer-Thread
omg omg omg...kann es wirklich sein? http://www.microsoft.com/en-us/download ... x?id=35515
-
- Establishment
- Beiträge: 201
- Registriert: 07.07.2010, 13:00
- Kontaktdaten:
Re: Anti-Jammer-Thread
Awww...yeah!111Part 6 is a special episode in which Stephan takes a look at the latest C++11 features that were just added to the Visual C++ compiler:
Variadic templates
Raw string literals
Explicit conversion operators
Default template arguments for function templates
Delegating constructors
Uniform initialization
Imaging-Software und bald auch Middleware: http://fd-imaging.com
- Schrompf
- Moderator
- Beiträge: 5211
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: Anti-Jammer-Thread
Uuuuuunglaublich! Mensch, das sind doch mal gute Neuigkeiten zum Samstag!
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
- Krishty
- Establishment
- Beiträge: 8364
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Anti-Jammer-Thread
http://msdn.microsoft.com/en-us/library/9598wk25.aspx
Wieder 200 B gespart.
Wieder 200 B gespart.
- Krishty
- Establishment
- Beiträge: 8364
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Anti-Jammer-Thread
Nach zehn Jahren habe ich Fensterklassen halbwegs verstanden und eine minimale C++-Klasse geschrieben, die es tatsächlich schafft, ein stinknormales Anzeigefenster objektorientiert zu kapseln. Ich Superheld ich.
Warum benutzt unser FAQ-WndProc-in-Klasse-unterbring-Artikel eigentlich nicht den letzten Parameter von CreateWindowEx(), um den Zeiger in WM_NCCREATE zu setzen? Es ist doch so einfach.
Warum benutzt unser FAQ-WndProc-in-Klasse-unterbring-Artikel eigentlich nicht den letzten Parameter von CreateWindowEx(), um den Zeiger in WM_NCCREATE zu setzen? Es ist doch so einfach.
- dot
- Establishment
- Beiträge: 1748
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Anti-Jammer-Thread
Hehe, meine Standardlösung dafür:
Ich bin aber nicht ganz zufrieden damit, auch wenn ich schon lang nimmer dran gebastelt hab. Im Idealfall würde der Object Pointer nur bei den Messages ausgelesen, deren Behandlung ihn auch erfordert...
Code: Alles auswählen
#ifndef INCLUDED_WIN32_WINDOW_CLASS
#define INCLUDED_WIN32_WINDOW_CLASS
#pragma once
#include "WindowHandle.h"
namespace Win32
{
template <class T, LRESULT (T::*WndProc)(HWND, UINT, WPARAM, LPARAM)>
class WindowClass
{
private:
ATOM cls;
static LRESULT CALLBACK BootstrapWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_CREATE)
{
T* obj = static_cast<T*>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams);
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(obj));
SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&WndProcThunk));
return (obj->*WndProc)(hWnd, msg, wParam, lParam);
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
static LRESULT CALLBACK WndProcThunk(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
T* obj = reinterpret_cast<T*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
return (obj->*WndProc)(hWnd, msg, wParam, lParam);
}
public:
WindowClass(LPCWSTR lpszClassName,
UINT style,
HICON hIcon,
HICON hIconSm,
HCURSOR hCursor,
HBRUSH hbrBackground = (HBRUSH)(COLOR_WINDOW + 1),
LPCTSTR lpszMenuName = nullptr)
{
WNDCLASSEXW wnd_cls;
wnd_cls.cbSize = sizeof(wnd_cls);
wnd_cls.style = style;
wnd_cls.lpfnWndProc = &BootstrapWndProc;
wnd_cls.cbClsExtra = 0;
wnd_cls.cbWndExtra = 0;
wnd_cls.hInstance = GetModuleHandleW(nullptr);
wnd_cls.hIcon = hIcon;
wnd_cls.hCursor = hCursor;
wnd_cls.hbrBackground = hbrBackground;
wnd_cls.lpszMenuName = lpszMenuName;
wnd_cls.lpszClassName = lpszClassName;
wnd_cls.hIconSm = hIconSm;
cls = RegisterClassExW(&wnd_cls);
}
~WindowClass()
{
UnregisterClassW(reinterpret_cast<LPCWSTR>(cls), GetModuleHandleW(nullptr));
}
WindowHandle createWindow(T& obj,
DWORD dwExStyle,
LPCWSTR lpWindowName,
DWORD dwStyle,
int X = CW_USEDEFAULT,
int Y = CW_USEDEFAULT,
int nWidth = CW_USEDEFAULT,
int nHeight = CW_USEDEFAULT,
HWND hWndParent = 0,
HMENU hMenu = 0)
{
return WindowHandle(CreateWindowExW(dwExStyle,
reinterpret_cast<LPCWSTR>(cls),
lpWindowName,
dwStyle,
X,
Y,
nWidth,
nHeight,
hWndParent,
hMenu,
GetModuleHandleW(nullptr),
&obj));
}
};
}
#endif // INCLUDED_WIN32_WINDOW_CLASS
- Krishty
- Establishment
- Beiträge: 8364
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Anti-Jammer-Thread
Guter Punkt – du hast eine Fensterklasse für alle Fenster, die mit einem Kontext-Objekt kommen; ich bin spezialisierter und hatte schon eine bestimmte Fensterart vor Augen. Deins sieht auf jeden Fall eleganter aus (zumal es keine virtuellen Funktionen braucht); ich grüble nur, wie ich sauber String-Literale ins Template kriege …
Dies und das: Ich setze den Zeiger schon in WM_NCCCREATE und lese ihn, wie erwähnt, nur für die Nachrichten, die ihn brauchen. Die WNDCLASSEX-Instanz ist bei mir static const; selbst ihr GetModuleHandleW(nullptr) kann man zur Übersetzungszeit durch reinterpret_cast<HMODULE>(__ImageBase) auflösen.
Dies und das: Ich setze den Zeiger schon in WM_NCCCREATE und lese ihn, wie erwähnt, nur für die Nachrichten, die ihn brauchen. Die WNDCLASSEX-Instanz ist bei mir static const; selbst ihr GetModuleHandleW(nullptr) kann man zur Übersetzungszeit durch reinterpret_cast<HMODULE>(__ImageBase) auflösen.
Re: Anti-Jammer-Thread
Ganz einfach: NCCREATE ist nicht die erste sinnvolle Message, die man in der WndProc bekommt. Daher erhält man den Pointer auf die Klasse eventuell zu spät. Frag mich aber nicht welche Messages noch davor kommen, ich erinnere mich nicht mehr dran. Da ich damals diese (eine?) Message brauchte, war der TLS meine bevorzugte Wahl. Und noch ein Hinweis von mir: Passt bloß auf, dass in CALLBACKs keine Exceptions „nach Außen“ gelangen … Das passiert schneller als man denkt in C++ Code, vor allem in den benutzerdefinierten WndProcs.Krishty hat geschrieben:Warum benutzt unser FAQ-WndProc-in-Klasse-unterbring-Artikel eigentlich nicht den letzten Parameter von CreateWindowEx(), um den Zeiger in WM_NCCREATE zu setzen? Es ist doch so einfach.
- Krishty
- Establishment
- Beiträge: 8364
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Anti-Jammer-Thread
Die allererste Nachricht ist WM_GETMINMAXINFO (damit das Fenster direkt mit der richtigen Größe erzeugt wird). Danach geht es direkt mit WM_NCCREATE weiter.
Wenn die Erzeugung eh im Kontext einer bestimmten Implementierung geschieht, kann man den auch dafür benutzen, das Fenster direkt mit der richtigen Größe zu erzeugen. Dann kann das erste WM_GETMINMAXINFO ruhig unbehandelt bzw. stanard-behandelt bleiben.
Wenn die Erzeugung eh im Kontext einer bestimmten Implementierung geschieht, kann man den auch dafür benutzen, das Fenster direkt mit der richtigen Größe zu erzeugen. Dann kann das erste WM_GETMINMAXINFO ruhig unbehandelt bzw. stanard-behandelt bleiben.
- dot
- Establishment
- Beiträge: 1748
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Anti-Jammer-Thread
Wofür genau die String Literale?Krishty hat geschrieben:Guter Punkt – du hast eine Fensterklasse für alle Fenster, die mit einem Kontext-Objekt kommen; ich bin spezialisierter und hatte schon eine bestimmte Fensterart vor Augen. Deins sieht auf jeden Fall eleganter aus (zumal es keine virtuellen Funktionen braucht); ich grüble nur, wie ich sauber String-Literale ins Template kriege …
Ja, das GetModuleHandle(nullptr) ist einzig und allein aus Faulheit drin. Auf jeden Fall danke für den Hinweis. Ich bin nur kein großer Fan der __ImageBase Variante, weil sie eigentlich auf mehr oder weniger undokumentiertem Verhalten basiert. GetModuleHandleEx() mit GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS bzw. einfach ein optionales HMODULE als Konstruktorparameter, wäre wohl die noch bessere Lösung.Krishty hat geschrieben:Dies und das: Ich setze den Zeiger schon in WM_NCCCREATE und lese ihn, wie erwähnt, nur für die Nachrichten, die ihn brauchen. Die WNDCLASSEX-Instanz ist bei mir static const; selbst ihr GetModuleHandleW(nullptr) kann man zur Übersetzungszeit durch reinterpret_cast<HMODULE>(__ImageBase) auflösen.
Natürlich hat deine Variante den Vorteil, dass wirklich von Anfang an alle Messages an die Methode weitergeleitet werden. Und ich muss zugeben, dass ich an TLS in dem Kontext noch gar nicht gedacht hab; aber TLS ist eine doch relativ knappe Ressource, die ich persönlich nur sehr ungern für sowas einsetzen würde...Biolunar hat geschrieben:Ganz einfach: NCCREATE ist nicht die erste sinnvolle Message, die man in der WndProc bekommt. Daher erhält man den Pointer auf die Klasse eventuell zu spät. Frag mich aber nicht welche Messages noch davor kommen, ich erinnere mich nicht mehr dran. Da ich damals diese (eine?) Message brauchte, war der TLS meine bevorzugte Wahl. Und noch ein Hinweis von mir: Passt bloß auf, dass in CALLBACKs keine Exceptions „nach Außen“ gelangen … Das passiert schneller als man denkt in C++ Code, vor allem in den benutzerdefinierten WndProcs.Krishty hat geschrieben:Warum benutzt unser FAQ-WndProc-in-Klasse-unterbring-Artikel eigentlich nicht den letzten Parameter von CreateWindowEx(), um den Zeiger in WM_NCCREATE zu setzen? Es ist doch so einfach.
Bezüglich Exceptions: http://www.altdevblogaday.com/2012/07/0 ... esnt-work/ ;)
Ich verwend WM_CREATE, weil es mir als das Logischste erschien. Früher hab ich überhaupt den Pointer erst nach dem CreateWindowEx() per SetWindowLongPtr() gesetzt, bis ich eines Tages eben auch mal auf die Idee kam, den lpParam von CreateWindowEx() zu benutzen. Das Problem ist, dass die genaue Abfolge an Messages, die CreateWindowEx() sendet, bevor es returned, nicht wirklich dokumentiert ist. Wobei ich mir auch überlegen werd, vielleicht WM_NCCREATE zu verwenden, nachdem das etwas früher kommt...Krishty hat geschrieben:Die allererste Nachricht ist WM_GETMINMAXINFO (damit das Fenster direkt mit der richtigen Größe erzeugt wird). Danach geht es direkt mit WM_NCCREATE weiter.
Wenn die Erzeugung eh im Kontext einer bestimmten Implementierung geschieht, kann man den auch dafür benutzen, das Fenster direkt mit der richtigen Größe zu erzeugen. Dann kann das erste WM_GETMINMAXINFO ruhig unbehandelt bzw. stanard-behandelt bleiben.
- Krishty
- Establishment
- Beiträge: 8364
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Anti-Jammer-Thread
WM_NCCREATE bedeutet, dass die Erzeugung des Fensterobjekts beginnt; nach WM_CREATE schließt sie ab. (Bei der Zerstörung ist es genau umgekehrt.)
Welche Nachrichten genau eintreffen ist nicht dokumentiert (das Fenster wird ja je nach Darstellungsart, Sichtbarkeit usw. noch aktiviert, in der Größe angepasst usw); für die vier (NC)CREATE/DESTROY-Nachrichten ist die Reihenfolge aber auf der MSDN definiert.
Ups, die Hälfte vergessen: Den String möchte ich als statischen Parameter reinkriegen, damit die Klassenbeschreibung beim Kompilieren als Read-only-Data angelegt wird (genau wie __ImageBase).
Was dein ATOM angeht, scheint das nicht die allerbeste Lösung zu sein:
Welche Nachrichten genau eintreffen ist nicht dokumentiert (das Fenster wird ja je nach Darstellungsart, Sichtbarkeit usw. noch aktiviert, in der Größe angepasst usw); für die vier (NC)CREATE/DESTROY-Nachrichten ist die Reihenfolge aber auf der MSDN definiert.
Ups, die Hälfte vergessen: Den String möchte ich als statischen Parameter reinkriegen, damit die Klassenbeschreibung beim Kompilieren als Read-only-Data angelegt wird (genau wie __ImageBase).
Was dein ATOM angeht, scheint das nicht die allerbeste Lösung zu sein:
http://blogs.msdn.com/b/oldnewthing/archive/2004/10/11/240744.aspx hat geschrieben:But what good is the atom?
Not much, really.
- dot
- Establishment
- Beiträge: 1748
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Anti-Jammer-Thread
Ja, so ist es wohl und macht auch Sinn, in der MSDN konnte ich aber bisher noch keine Dokumentation zu diesem Verhalten finden. Man beachte, dass nirgendwo steht, dass die Reihenfolge, in der die Nachrichten aufgelistet sind, auch tatsächlich die Reihenfolge ist, in der die Nachrichten gesendet werden. Die Dokumentation zu CreateWindow() listet sie sogar in anderer Reihenfolge als die von CreateWindowEx(), obwohl eigentlich beides die selbe Funktion ist (was aber natürlich auch nirgendwo wirklich dokumentiert ist)...Krishty hat geschrieben:WM_NCCREATE bedeutet, dass die Erzeugung des Fensterobjekts beginnt; nach WM_CREATE schließt sie ab. (Bei der Zerstörung ist es genau umgekehrt.)
Naja, ich verwend das ATOM, damit ich net den ganzen String kopieren muss. Natürlich wäre es noch besser, den String irgendwie statisch reinzubekommen, aber das müsste man wenn dann wohl als Template Argument und für String Literale funktoniert das nicht. Man könnte wohl mit Template Metaprogramming was machen, vielleicht einfach direkt, z.B. basierend auf der Adresse einer Methode, einen eindeutigen String generieren...das wars mir bisher aber noch nicht wert...Krishty hat geschrieben:Was dein ATOM angeht, scheint das nicht die allerbeste Lösung zu sein:http://blogs.msdn.com/b/oldnewthing/archive/2004/10/11/240744.aspx hat geschrieben:But what good is the atom?
Not much, really.
Aber gut, ich dachte mir schon fast, dass du mit den String Literalen das meintest und da hast du natürlich recht, das wäre eine noch bessere Lösung...
- Krishty
- Establishment
- Beiträge: 8364
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: Anti-Jammer-Thread
dot hat geschrieben:Ja, so ist es wohl und macht auch Sinn, in der MSDN konnte ich aber bisher noch keine Dokumentation zu diesem Verhalten finden. Man beachte, dass nirgendwo steht, dass die Reihenfolge, in der die Nachrichten aufgelistet sind, auch tatsächlich die Reihenfolge ist, in der die Nachrichten gesendet werden.
http://msdn.microsoft.com/de-de/library/windows/desktop/ms632635 hat geschrieben:[WM_NCCREATE is] Sent prior to the WM_CREATE message when a window is first created.
Wenn du jetzt noch irgendwo findest, dass Fenster erst nach ihrer Erzeugung zerstört werden, ist die Reihenfolge WM_NCCREATE; WM_CREATE; WM_DESTROY; WM_NCDESTROY offiziell dokumentiert. Oder was meinst du?http://msdn.microsoft.com/en-us/library/windows/desktop/ms632636 hat geschrieben:The DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY message.
- dot
- Establishment
- Beiträge: 1748
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Anti-Jammer-Thread
Ok, damit ist es wohl ausreichend definiert :)
- dot
- Establishment
- Beiträge: 1748
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Anti-Jammer-Thread
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:
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...
Code: Alles auswählen
const char* static blub = "abc"; // OK
const char* blab = blub; // OK
const char* static blob = blab; // error
EDIT: Wobei das im konkreten Fall wohl auch nur ein etwas besserer Ersatz für das ATOM wär...
- CodingCat
- Establishment
- Beiträge: 1857
- Registriert: 02.03.2009, 21:25
- Wohnort: Student @ KIT
- Kontaktdaten:
Re: Anti-Jammer-Thread
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
}
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
- dot
- Establishment
- Beiträge: 1748
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Anti-Jammer-Thread
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):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.
Code: Alles auswählen
local int x; // OK
local int* local px = &x; // OK
int** blub = new int*;
*blub = &px; // error
Zuletzt geändert von dot am 04.11.2012, 16:54, insgesamt 1-mal geändert.
- CodingCat
- Establishment
- Beiträge: 1857
- Registriert: 02.03.2009, 21:25
- Wohnort: Student @ KIT
- Kontaktdaten:
Re: Anti-Jammer-Thread
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.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...
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
- dot
- Establishment
- Beiträge: 1748
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Anti-Jammer-Thread
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...
- CodingCat
- Establishment
- Beiträge: 1857
- Registriert: 02.03.2009, 21:25
- Wohnort: Student @ KIT
- Kontaktdaten:
Re: Anti-Jammer-Thread
Das Problem ist, sobald es implizit funktioniert, vergisst man, es richtig zu machen. Genau wie bei const-Correctness.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
- dot
- Establishment
- Beiträge: 1748
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Anti-Jammer-Thread
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:
Der dynamic und static Qualifier darf implizit wegkonvertiert werden, local dagegen nicht:
Edit: Verdammt, wenn man im ersten Beispiel aber *blub an px zuweisen will, gehts wieder nicht...
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*
}
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*
}
Zuletzt geändert von dot am 04.11.2012, 17:38, insgesamt 1-mal geändert.
- CodingCat
- Establishment
- Beiträge: 1857
- Registriert: 02.03.2009, 21:25
- Wohnort: Student @ KIT
- Kontaktdaten:
Re: Anti-Jammer-Thread
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:
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:
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
}
Nachtrag: Die Lösung über die externe Referenz funktioniert nicht, es braucht wohl tatsächlich einen dritten Mischtypen extern local. :mrgreen:
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
- dot
- Establishment
- Beiträge: 1748
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Anti-Jammer-Thread
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
- CodingCat
- Establishment
- Beiträge: 1857
- Registriert: 02.03.2009, 21:25
- Wohnort: Student @ KIT
- Kontaktdaten:
Re: Anti-Jammer-Thread
Ich verstehe noch nicht ganz, wozu du hier Deduktion brauchst. Ist das Ziel nicht gerade, Sicherheit durch wohldefinierte Konvertierungsregeln zu schaffen?
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
- dot
- Establishment
- Beiträge: 1748
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Anti-Jammer-Thread
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...
- CodingCat
- Establishment
- Beiträge: 1857
- Registriert: 02.03.2009, 21:25
- Wohnort: Student @ KIT
- Kontaktdaten:
Re: Anti-Jammer-Thread
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.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
- dot
- Establishment
- Beiträge: 1748
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Anti-Jammer-Thread
Ok, verwenden wir statt auto einfach local, einer der beiden ist in meinem obigen Modell eigentlich sowieso überflüssig. Folgende Regeln:
Edit: Verdammt, bei h = y geht's wieder kaputt...
- 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*
}
Zuletzt geändert von dot am 04.11.2012, 19:39, insgesamt 1-mal geändert.
- CodingCat
- Establishment
- Beiträge: 1857
- Registriert: 02.03.2009, 21:25
- Wohnort: Student @ KIT
- Kontaktdaten:
Re: Anti-Jammer-Thread
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:
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
Zuletzt geändert von CodingCat am 04.11.2012, 19:51, insgesamt 1-mal geändert.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
- dot
- Establishment
- Beiträge: 1748
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Anti-Jammer-Thread
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...