 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Marcel Müller Guest
|
Posted: Wed Jun 15, 2005 8:17 pm Post subject: Sematischer unterschied zischen "type name(constr_arg);" und |
|
|
Hallo,
gibt es eingentlich jenseits der unterschiedlichen Syntax einen
semantischen Unterschied zwischen den beiden Schreibweisen
my_type my_var(expression);
und
my_type my_var = expression;
?
Meines Wissens sollte doch beides einen zum Typ von expression passenden
Konstruktor von my_type aufrufen.
Hintergrund:
Ich versuche gerade ein Programm der Art
template <typename T>
struct my_type_ref
{ my_type_ref() { }
};
template <typename T>
struct my_type
{ my_type() { }
my_type(T* p) { }
my_type(my_type<T>& r) { }
my_type(my_type_ref<T> r) { }
operator my_type_ref<T>() { }
};
int main()
{ my_type<int> x(new int()); // geht
my_type<int> y = new int(); // Fehler!
}
zu übersetzen. Aber in der markierten Zeile gibt es einen Fehler, den
ich mir nicht erklären kann (gcc 3.3.5).
testx.cpp: In function `int main()':
testx.cpp:17: error: no matching function for call to
`my_type<int>::my_type(my_type<int>)'
testx.cpp:11: error: candidates are:
my_type<T>::my_type(my_type_ref<T>) [with T = int]
testx.cpp:10: error: my_type<T>::my_type(my_type<T>&)
[with T = int]
testx.cpp:9: error: my_type<T>::my_type(T*) [with T = int]
testx.cpp:17: error: initializing temporary from result of
`my_type<T>::my_type(T*) [with T = int]'
testx.cpp:18:2: warning: no newline at end of file
Offenbar versucht der Compiler ein temporäres Objekt zu erzeugen (gut,
wenn er meint), dann aber den auto_ptr-artigen Umweg über den Typ
my_type_ref nicht hinzubekommen.
Den gewünschten Konstruktor my_type<int>::my_type(my_type<int>) kann es
ja nicht geben. Höchstens my_type<int>::my_type(my_type<int>&) oder
my_type<int>::my_type(const my_type<int>&) - der klassische
Copy-Konstruktor, der hier nicht erwünscht ist.
Oder hat der Compiler einfach eine Macke?
Marcel
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Rolf Magnus Guest
|
Posted: Thu Jun 16, 2005 9:13 am Post subject: Re: Sematischer unterschied zischen "type name(constr_arg);" |
|
|
Marcel Müller wrote:
| Quote: | Hallo,
gibt es eingentlich jenseits der unterschiedlichen Syntax einen
semantischen Unterschied zwischen den beiden Schreibweisen
my_type my_var(expression);
und
my_type my_var = expression;
?
Meines Wissens sollte doch beides einen zum Typ von expression passenden
Konstruktor von my_type aufrufen.
|
Soweit schon. Aber die erste Variante erzeugt my_var direkt über den
"passenden" Konstruktor, während die zweite Variante mit diesem erst ein
temporäres Objekt vom Typ my_type konstruiert, dieses dann per
Kopierkonstruktor nach my_var kopiert, dann das temporäre Objekt wieder
löscht. Moderne Compiler können dieses temporäre Objekt wegoptimieren, so
daß im Prinzip das gleiche wie in der ersten Variante passiert. Die
C++-Norm erlaubt das auch explizit, aber da die Validität von Code nicht
vom Optimierungsverhalten des Compilers abhängen darf, muß in diesem Fall
trotzdem verlangt werden, daß der Kopierkonstruktor verfügbar ist.
| Quote: | Hintergrund:
Ich versuche gerade ein Programm der Art
template <typename T
struct my_type_ref
{ my_type_ref() { }
};
template
struct my_type
{ my_type() { }
my_type(T* p) { }
my_type(my_type
my_type(my_type_ref<T> r) { }
operator my_type_ref<T>() { }
};
int main()
{ my_type<int> x(new int()); // geht
my_type<int> y = new int(); // Fehler!
}
zu übersetzen. Aber in der markierten Zeile gibt es einen Fehler, den
ich mir nicht erklären kann (gcc 3.3.5).
testx.cpp: In function `int main()':
testx.cpp:17: error: no matching function for call to
`my_type<int>::my_type(my_type<int>)'
testx.cpp:11: error: candidates are:
my_type<T>::my_type(my_type_ref<T>) [with T = int]
testx.cpp:10: error: my_type<T>::my_type(my_type<T>&)
[with T = int]
testx.cpp:9: error: my_type<T>::my_type(T*) [with T =
int]
testx.cpp:17: error: initializing temporary from result of
`my_type<T>::my_type(T*) [with T = int]'
testx.cpp:18:2: warning: no newline at end of file
Offenbar versucht der Compiler ein temporäres Objekt zu erzeugen (gut,
wenn er meint),
|
Richtig.
| Quote: | dann aber den auto_ptr-artigen Umweg über den Typ my_type_ref nicht
hinzubekommen.
Den gewünschten Konstruktor my_type<int>::my_type(my_type<int>) kann es
ja nicht geben. Höchstens my_type<int>::my_type(my_type<int>&) oder
my_type<int>::my_type(const my_type<int>&) - der klassische
Copy-Konstruktor, der hier nicht erwünscht ist.
|
Nun, dein Konstruktor nimmt eine nicht-const-Referenz an. An diese kann man
aber keine temporären Objekte binden. Da die C++-Norm vorschreibt, daß ein
Kopierkonstruktor verfügbar ist, der mit einem temporären Objekt klarkommt,
funktioniert das so nicht.
| Quote: | Oder hat der Compiler einfach eine Macke?
|
Nein, das Verhalten ist völlig konform.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Marcel Müller Guest
|
Posted: Fri Jun 17, 2005 12:10 am Post subject: Re: Sematischer unterschied zischen "type name(constr_arg);" |
|
|
Rolf Magnus schrieb:
| Quote: | my_type my_var(expression);
und
my_type my_var = expression;
Soweit schon. Aber die erste Variante erzeugt my_var direkt über den
"passenden" Konstruktor, während die zweite Variante mit diesem erst ein
temporäres Objekt vom Typ my_type konstruiert, dieses dann per
Kopierkonstruktor nach my_var kopiert, dann das temporäre Objekt wieder
löscht. Moderne Compiler können dieses temporäre Objekt wegoptimieren, so
daß im Prinzip das gleiche wie in der ersten Variante passiert. Die
C++-Norm erlaubt das auch explizit, aber da die Validität von Code nicht
vom Optimierungsverhalten des Compilers abhängen darf, muß in diesem Fall
trotzdem verlangt werden, daß der Kopierkonstruktor verfügbar ist.
|
Soweit klar, aber warum funktioniert in diesem Fall der Umweg über
my_type_ref nicht? Das Codeschnipsel
my_type<B> foo();
void bar(my_type<B> p);
int main()
{ my_type<B> x(foo());
bar(x);
}
funktioniert ja schließlich auch, obwohl zweimal der Copy-Konstruktor
benötigt wird. Statt dessen wird halt my_type::operator my_type_ref()
gefolgt von my_type::my_type(my_type_ref) aufgerufen.
| Quote: | Nun, dein Konstruktor nimmt eine nicht-const-Referenz an. An diese kann man
aber keine temporären Objekte binden. Da die C++-Norm vorschreibt, daß ein
Kopierkonstruktor verfügbar ist, der mit einem temporären Objekt klarkommt,
funktioniert das so nicht.
|
Naja, die Norm sagt aber auch, daß sich ein Objekt mit definiertem
operator my_type_ref() überall da verwendet werden kann, wo auch ein
my_type_ref erlaubt ist. Und my_type ist doch über my_type_ref
konstruierbar. Das ist ja gerade der Trick, der auch bei auto_ptr
eingesetzt wird.
| Quote: | Oder hat der Compiler einfach eine Macke?
Nein, das Verhalten ist völlig konform.
|
Irgendwie verstehe ich das noch nicht.
Marcel
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|