Standardkonstruktor in einem Konstruktoraufruf aufrufen
-
Hallo Community,
ich habe ein Problem mit einem Konstruktoraufruf.
Ich zeige zunaechst den Code (die Fragen stehen im Prinzip auch schon in den Kommentaren). Lasst euch nicht von den Templates verwirren, die haben (meine ich) nichts mit dem Problem zu tun. Ich bin nur beim lernen von Template-Programmierung drauf gestossen.#include <initializer_list> #include <iostream> using namespace std; struct MyStruct { int x; MyStruct (int x = 1) : x (x) {} void operator() () { // mach was mit x } }; template<class T> class MyClass { public: MyClass (T const& t = MyStruct() ) : t (t) {} void doSomething() const { // mach was mit t } private: T t; }; template<class T> void func (T t) { t(); } int main() { MyClass<MyStruct> objA; // a) geht (wie erwartet) objA.doSomething(); MyClass<MyStruct> objB(); // b) geht nicht, (wie erwartet) objB.doSomething(); MyClass<MyStruct> objC (MyStruct() ); // c) geht nicht, warum? d) und f) gehen doch auch !? objC.doSomething(); MyClass<MyStruct> objD (MyStruct (42) ); // d) geht (wie erwartet) objD.doSomething(); MyClass<MyStruct> objE { MyStruct() }; // e) geht (wie erwartet) objE.doSomething(); func (MyStruct() ); // f) geht (wie erwartet) return EXIT_SUCCESS; }
a), b) und e) sind mir soweit eigentlich klar. Mein Problem ist, dass c) nicht geht, d) und f) aber schon. Was uebersehe ich da?
Der Compiler meckert in den Zeilen 37 und 40:
error C2228: Links von ".doSomething" muss sich eine Klasse/Struktur/Union befinden.
Wenn ich diese Zeilen auskommentiere (also
doSomething()
fuerobjB
undobjC
nicht aufrufe), bekomme ich folgende Warnung:...\main.cpp(37): warning C4930: 'MyClass<MyStruct> objB(void)': Funktion mit Prototyp wurde nicht aufgerufen (war eine Variablendefinition gemeint?)
...\main.cpp(40): warning C4930: 'MyClass<MyStruct> objC(MyStruct (__cdecl *)(void))': Funktion mit Prototyp wurde nicht aufgerufen (war eine Variablendefinition gemeint?)Soll das heissen, dass ich hier eine Funktion deklariert habe, die
MyClass<MyStruct>
zurueckgibt und als Parameter einen Zeiger auf eine Funktion erwartet, die einMyStruct
zurueckgibt?
Das wuerde doch eigentlich so aussehen:MyClass<MyStruct> objC (MyStruct (*func) () );
Aber vor allem wundert es mich, dass ich auf dieses Problem noch nicht frueher gestossen bin
Als IDE verwende ich Visual Studio 2013 mit entsprechendem Compiler (Toolset v120).
Vielen Dank fuer eure Hilfe!
Gruss
MatzeEdit: '=' bei objE entfernt
-
Das Problem ist bekannt als "Most Vexing Parse" und beschreibt eine Mehrdeutigkeit in der C++-Syntax. Und zwar werden die entsprechenden Variablendefinitionen als Funktionsdeklarationen erkannt.
MatzeHHC schrieb:
Lasst euch nicht von den Templates verwirren, die haben (meine ich) nichts mit dem Problem zu tun.
Dann lass sie doch nächstes Mal weg. Ideal ist ein vollständiges, kompilierbares Minimalbeispiel, anhand dessen wir das Problem erkennen können.
-
Nexus schrieb:
Das Problem ist bekannt als "Most Vexing Parse" und beschreibt eine Mehrdeutigkeit in der C++-Syntax. Und zwar werden die entsprechenden Variablendefinitionen als Funktionsdeklarationen erkannt.
Danke, mein Problem war, dass ich nicht wusste, dass
MyStruct()
als namenloser Funktionszeiger interpretiert werden kann (stimmt das so )
ich kannte nur
MyStruct(*)()
Sorry wegen der Templates...
Gruß
Matze
-
Kennste std::function?
Da schreibste ja auch void() in den Parametern.
-
Nathan schrieb:
Kennste std::function?
Da schreibste ja auch void() in den Parametern.stimmt
-
MatzeHHC schrieb:
Danke, mein Problem war, dass ich nicht wusste, dass
MyStruct()
als namenloser Funktionszeiger interpretiert werden kann (stimmt das so )
Nein, mit Funktionszeigern hat das nichts zu tun.
MyClass<MyStruct> objC (MyStruct());
ist aufgrund einer fragwürdigen Syntaxregel das gleiche wie
MyClass<MyStruct> objC (MyStruct);
was eine Funktionsdeklaration darstellt.
Ich bin mir auch nicht sicher, wer es für eine gute Idee hielt, Klammern um Parametertypen zuzulassen. Oder generell um Typen in Deklarationskontexten.
Nathan schrieb:
Kennste std::function?
Da schreibste ja auch void() in den Parametern.Das
void()
bedeutet was anderes als hier. Insbesondere ist es kein Funktionszeiger.
-
Nexus schrieb:
MyClass<MyStruct> objC (MyStruct());
ist aufgrund einer fragwürdigen Syntaxregel das gleiche wie
MyClass<MyStruct> objC (MyStruct);
was eine Funktionsdeklaration darstellt.
Laut:
MSVC schrieb:
warning C4930: 'MyClass<MyStruct> objC(MyStruct (__cdecl *)(void))': Funktion mit Prototyp wurde nicht aufgerufen (war eine Variablendefinition gemeint?)
scheint VC daraus aber:
MyClass<MyStruct> objC(MyStruct (__cdecl *)(void))
zu machen.
Laut ideone auch: http://ideone.com/IH92h2Insbesondere ist es kein Funktionszeiger.
Was dann?
-
Nexus schrieb:
MatzeHHC schrieb:
Danke, mein Problem war, dass ich nicht wusste, dass
MyStruct()
als namenloser Funktionszeiger interpretiert werden kann (stimmt das so )
Nein, mit Funktionszeigern hat das nichts zu tun.
MyClass<MyStruct> objC (MyStruct());
ist aufgrund einer fragwürdigen Syntaxregel das gleiche wie
MyClass<MyStruct> objC (MyStruct);
was eine Funktionsdeklaration darstellt.
Da verstehe ich meine Compiler-Warnung aber anders:
Compiler schrieb:
...\main.cpp(40): warning C4930: 'MyClass<MyStruct> objC(MyStruct (__cdecl *)(void))': Funktion mit Prototyp wurde nicht aufgerufen (war eine Variablendefinition gemeint?)
Und den Wikipediaeintrag:
http://en.wikipedia.org/wiki/Most_vexing_parseWikipedia schrieb:
The line
TimeKeeper time_keeper(Timer());
could be disambiguated either as
1. a variable definition for variable time_keeper of class TimeKeeper, passed an anonymous instance of class Timer or
2. a function declaration for a function time_keeper which returns an object of type TimeKeeper and takes a single (unnamed) argument which is a function returning type Timer (and taking no input). (See Function object#In C and C++)Jetzt bin ich verwirrt
-
Ihr habt Recht, die Klammern stehen ja nach dem Parametertyp. Wie auch immer, jedenfalls wird die naheliegende Variante nicht bevorzugt
Nathan schrieb:
Insbesondere ist es kein Funktionszeiger.
Was dann?
Eine Funktion.
-
Nexus schrieb:
Nathan schrieb:
Insbesondere ist es kein Funktionszeiger.
Was dann?
Eine Funktion.
...was im Kontext einer Funktionsdeklaration scheinbar dasselbe ist:
http://ideone.com/3cPHMu
-
Nathan schrieb:
was im Kontext einer Funktionsdeklaration scheinbar dasselbe ist
Du meinst wohl, im Kontext eines Funktionsparameters? Ist dasselbe wie mit Arrays
After determining the type of each parameter, any parameter of type “array of T” or “function returning T” is adjusted to be “pointer to T” or “pointer to function returning T,” respectively.
Nexus schrieb:
Ein Funktionstyp.
FTFY
-
Arcoth schrieb:
Ist dasselbe wie mit Arrays
After determining the type of each parameter, any parameter of type “array of T” or “function returning T” is adjusted to be “pointer to T” or “pointer to function returning T,” respectively.
Stimmt, mit Arrays ist das ja gleich.