Eure Wünsche an Sprachfeatures für den nächsten Standard (nach C++11)
-
ipsec schrieb:
...Zero Overhead...
Das stimmt nicht.
ipsec schrieb:
...wiese sollte man es dann als Sprachfeature umsetzen?...
Ob man es sollte oder nicht, dazu nahm ich gar nicht Stellung.
-
Kannst Du mal ein Beispiel nennen, wo das nützlich wäre?
Marshalling.
-
Vorbemerkung: Vielleicht bin ich ja nur zu blöd, das mit C++11 zu lösen, dann bin ich für jede Hilfe dankbar.
Was mir fehlt, sind Container, in die ich Objekte aus einer Klassenhierarchie stecken kann, um dann später Methoden polymorph aufzurufen. Also etwa
class A { virtual void foo(); }; class B : public A { virtual void foo(); }; vector<? extends A> myVec; // an java Generics angelehnt void create(void) { A a; B b; myVec.push_back(a); myVec.push_back(b); } void use(vector<? extends A> vec) { for(size_t i(0); i<vec.size; ++i) { myVec[i].foo(); } }Heute löse ich das, in dem ich ein
vector<A*>nehme. Das ist aber insofern nicht schön, weil die Objekte ja in irgendeiner Form im Speicher vorhanden sein müssen (statisch oder heap) und die benutzende Klasse nicht ohne Weiteres weiß, wo der Speicher für das Objekt her kommt.Also muss ich entweder jedem Objekt mitgeben, wie es alloziert wurde, oder ich verwende doubleDispatch. Letzters macht den Code aber (nicht nur) in den Augen derjenigen, die das nachher warten müssen, komplizierter.
-
Stichwort: Smartpointer.
-
@PI: Wie soll der helfen? Das sind Templates, die, wenn ich die in den Container stecke, doch jeweils einen eigenen Typ bilden, oder?
class A { virtual void foo(); }; class B : public A { virtual void foo(); }; std::unique_ptr<A> a; std::unique_ptr<B> b; // ist ein anderer Typ als aOder meinst Du
class A { virtual void foo(); }; class B : public A { virtual void foo(); }; vector<std::unique_ptr<A>> myVec; myVec.push_back(new A); myVec.push_back(new B);Ich kann's hier leider gerade nicht ausprobieren.
-
class A { virtual void foo(); }; class B : public A { virtual void foo(); }; std::unique_ptr<A> a; std::unique_ptr<B> b; // ist AUCH ein A
-
Ah OK, da war Tachyon schneller (und bei mir ein klarer Fall von RTFM, weils in der VC10 Doku ja schon erklärt ist).
Bestens, danke!
-
Tachyon schrieb:
GorbGorb schrieb:
Das ist zwar etwas utopisch, aber ich wuerde mir mehr compile time reflection wuenschen. Vieles wurde ja schon umgesetzt, es fehlt aber noch die Moeglichkeit, eine Liste aller Member einer Klasse von ausserhalb abzufragen, ohne deren Namen, Anzahl oder Typ schon zu kennen.
Kannst Du mal ein Beispiel nennen, wo das nützlich wäre?
Da ich mich zur Zeit vor allem mit rtti beschäftige, etwas aus der Ecke: boost::any.
Man bekommt ein Objekt aus boost::any nur dann raus, wenn man nach exakt dem richtigen Typ fragt.
Sinnvoller wäre es meiner Ansicht nach, wenn man nur nach einer Basisklasse fragen müsste.
Das funktioniert momentan aber nicht, weil man bei boost::any_cast den Typ in boost::any noch nicht kennt, sondern nur eine id, die man mit der id des abgefragten Typs vergleicht.
Sinnvoller wäre es, man hätte gleichzeitig auch noch ids aller Basisklassen gespeichert. Um die zu speichern müsste man, wenn man ein Objekt in boost::any schiebt (hier kennt man ja den Typ des Objekts, er ist das template Parameter), herausfinden, welche Basisklassen zum Objekt gehören. Das ist momentan aber nicht möglich.Mir ist außerdem noch was eingefallen: ein static_if. Ohne mich großartig mit D beschäftigt zu haben, nehme ich an, dass mir so etwas wie aus D vorschwebt. In etwa so:
template< class Type > void func( Type First , Type Last ) { static_if( is_random_access< Type >::value ) { //code, der bei anderen Iteratoren zu compilerfehlern führen würde } else if( is_bidirectional< Type >::value ) { } else if( is_iterator< Type >::value ) { } else { } }Das könnte man zwar vermutlich auch mit concepts lösen, aber das hier ist denke ich flexibler einsetzbar.
-
Kannst du doch jetzt schon genauso machen? Der Compiler optimiert eh den Rest weg, wenn die Bedingungen schon zur Compilezeit true/false sind.
Edit: Dörgh, hab nur 2 Meter weit gedacht.
Ansonsten schreit das nach enable_if

template< class Type > void func(Type First, Type Last, typename std::enable_if<is_random_access<Type>>::type* = 0) { ... } template< class Type > void func(Type First, Type Last, typename std::enable_if<is_bidirectional<Type>>::type* = 0) { ... } template< class Type > void func(Type First, Type Last, typename std::enable_if<is_iterator<Type>>::type* = 0) { ... }
-
Meinst du einfach ein normales if verwenden?
Das funktioniert häufig, aber nicht immer, weil man z.B. in meinem Beispiel Operationen ausführen will, die der Typ nicht zwingend unterstützt. Nutzt man ein normales if, werden trotzdem alle branches ausgewertet, was zu compile Fehlern führen kann.
-
Ethon schrieb:
Ansonsten schreit das nach enable_if

Oder so kann man das Interface davor bewahren:
template <typename Iterator> void Func(Iterator first, Iterator last) { FuncImpl(first, last, typename std::iterator_traits<Iterator>::iterator_category()); } template <typename Iterator> void FuncImpl(Iterator first, Iterator last, std::random_access_iterator_tag); template <typename Iterator> void FuncImpl(Iterator first, Iterator last, std::bidirectional_iterator_tag);
-
GorbGorb schrieb:
Meinst du einfach ein normales if verwenden?
Das funktioniert häufig, aber nicht immer, weil man z.B. in meinem Beispiel Operationen ausführen will, die der Typ nicht zwingend unterstützt. Nutzt man ein normales if, werden trotzdem alle branches ausgewertet, was zu compile Fehlern führen kann.enable_if ist da trotzdem die bessere Methode, da es immer ungut ist, im Code selbst Templatetypen zu unterscheiden. Da lieber eine eigene Funktion pro Typ, auch wenn enable_if recht hässlich ist.
-
Nexus schrieb:
template <typename Iterator> void Func(Iterator first, Iterator last) { FuncImpl(first, last, typename std::iterator_traits<Iterator>::iterator_category()); } template <typename Iterator> void FuncImpl(Iterator first, Iterator last, std::random_access_iterator_tag); template <typename Iterator> void FuncImpl(Iterator first, Iterator last, std::bidirectional_iterator_tag);Ich weiß, dass es sowas gibt, aber kommt nur mir sowas extrem umständlich vor? Ich meine, was man im Grunde will, ist, in Abhängigkeit von einem bestimmten Wert unterschiedlichen code auszuführen. In jeder mir bekannten Programmiersprache (zugegeben, sind nicht viele) funktioniert sowas mit einem if. Nur in c++ tmp muss man dafür auf irgendwelche Hilfskonstrukte zurückgreifen, die Funktionsüberladung und evtl. sogar SFINAE verwenden, um sowas zu erreichen.
Ich bin mir sehr sicher, dass code mit einem static_if deutlich lesbarer würde.
-
Concepts. Dann bin ich glücklich. Ehrlich, einiges von dem was C++11 bringt, brauch ich gar nicht. Variadic templates werden sicherlich keinen großen impact haben, also abseits von Boost und ner handvoll anderer Bibliotheken. Concepts wären der Bringer gewesen...naja,vielleicht beim nächsten mal.
-
Nexus schrieb:
template <typename Iterator> void Func(Iterator first, Iterator last) { FuncImpl(first, last, typename std::iterator_traits<Iterator>::iterator_category()); } template <typename Iterator> void FuncImpl(Iterator first, Iterator last, std::random_access_iterator_tag); template <typename Iterator> void FuncImpl(Iterator first, Iterator last, std::bidirectional_iterator_tag);Frage am Rande, weiss das vielleicht einer? Darf der Kompiler hier den dritten Funktionsparameter wegoptimieren? Er wird ja nur dazu verwendet, um herauszufinden, welche Funktion aufgerufen wird. Somit ist der Parameter nur zur Kompilezeit relevant.
Oder wäre es vielleicht klüger dies wie folgt zu schreiben:
template<typename IteratorCategory> struct FuncImpl { }; template<> struct FuncImpl<std::random_access_iterator_tag> { template<typename Iterator> static void Call(Iterator first, Iterator last); }; template<> struct FuncImpl<std::bidirectional_iterator_tag> { template<typename Iterator> static void Call(Iterator first, Iterator last); }; template <typename Iterator> void Func(Iterator first, Iterator last) { FuncImpl<typename std::iterator_traits<Iterator>::iterator_category>.call(first, last); }Grüssli
-
otze schrieb:
Concepts. Dann bin ich glücklich. Ehrlich, einiges von dem was C++11 bringt, brauch ich gar nicht. Variadic templates werden sicherlich keinen großen impact haben, also abseits von Boost und ner handvoll anderer Bibliotheken. Concepts wären der Bringer gewesen...naja,vielleicht beim nächsten mal.
Was ich an variadic templates so genial finde, ist, dass man damit Beziehungen zwischen Objekten/Modulen abstrahieren kann, also die Softwarearchitektur modellieren kann.
Auch noch was zum Thema templates: Ich fände es ganz nett, wenn man bestimmte Restriktionen etwas lockern könnte:
- warum muss eine template Spezialiserung im namespace scope stehen (vc++ kann das z.B. auch in einer Klasse)
- warum können lokale Klassen in Funktionen keine template member haben?
-
GorbGorb schrieb:
- warum können lokale Klassen in Funktionen keine template member haben?
Können sie doch. Glaub ich.

-
Nexus schrieb:
template <typename Iterator> void Func(Iterator first, Iterator last) { FuncImpl(first, last, typename std::iterator_traits<Iterator>::iterator_category()); } template <typename Iterator> void FuncImpl(Iterator first, Iterator last, std::random_access_iterator_tag); template <typename Iterator> void FuncImpl(Iterator first, Iterator last, std::bidirectional_iterator_tag);Du musst die FuncImpl-Teampltes über der Definition von Func deklarieren. So, klappt das nur mit Microsoft's Compiler, weil der es nicht so genau nimmt mit dem Name-Lookup.
-
314159265358979 schrieb:
GorbGorb schrieb:
- warum können lokale Klassen in Funktionen keine template member haben?
Können sie doch. Glaub ich.

Kriegst du das zum Laufen?
int main() { class X { public: template< class Type > void func() { } }; }
-
GorbGorb schrieb:
int main() { class X { public: template< class Type > void func() { } }; }Ein Kommunikationsproblem also. Ich dachte, du meinst lokale Klassen, die in Funktionen stehen und Template Parameter haben.
Geht aber offenbar auch nicht. Da war doch mal was vonwegen lösen der Beschränkungen in C++11?
