Template-Template-Argumente, Defaultargumente und VC++ 2010



  • Ich habe einigen Code, der sowas macht:

    template <typename T, template <typename T> class ContT>
            static void pushBackOrFree (ContT<T*>& cont, T* value);
    

    In C++Builder funktioniert das auch schön, aber VC++ 2010 scheint zu erwarten, daß ich da schön alle Template-Argumente von ContT aufliste, also auch den Allokator und weitere Argumente, etwa bei std::basic_string<> noch den Trait-Parameter. Das finde ich natürlich ziemlich lästig, habe etwas nachgeforscht und dieses Paper gefunden, das in einer Fußnote auf S. 4 behauptet:

    The C++ Standardization Committee currently discusses if this a defect, inadequately restricting library writers.

    Das hieße also, VC++ hat recht und C++Builder ist zu nachlässig, was ich mir schon gedacht hatte.

    Weiß jemand, ob das in C++11 behoben wurde? Oder kann man sich ansonsten darauf verlassen, daß alle Standard-Container exakt zwei Template-Argumente haben und nicht irgendein STL-Anbieter (z.B. frühere Versionen der STL von SGI, wie das zitierte Paper behauptet) zusätzliche Argumente mit Defaultwerten hinzufügt?



  • Mich würd sehr interessieren, von wann dieses Paper ist. Da gibt es nicht zu beheben. Bei template template Parametern musst du eine passende Argumentliste angeben. Der C++ Standard legt genau fest, welche Argumente die Standard Container haben.



  • Gcc frisst mit -std=c++11 Folgendes:

    template<template<typename> class> struct foo { };
    
    template<typename T> using bar = std::vector<T>;
    
    foo<bar> baz;
    

    Ich bin mit dem neuen Standard noch nicht vertraut genug, um mich für die Konformität dieses Ansatzes zu verbürgen, aber für den Moment ist das ein Workaround.

    Wobei es erfahrungsgemäß in aller Regel sinnvoller ist, komplett konkretisierte Typen als Parameter anzugeben; die Standardcontainer haben ja den Allokator auch nicht als template<typename> class-Parameter.



  • template <typename...> class ContT
    


  • Vielen Dank für die Antworten.

    dot schrieb:

    Mich würd sehr interessieren, von wann dieses Paper ist.

    Adobe Reader zufolge vom 17.06.2002.

    dot schrieb:

    Da gibt es nicht zu beheben. Bei template template Parametern musst du eine passende Argumentliste angeben.

    Wunderbar - aber das hilft mir nichts, wenn ich std::basic_string<> und std::vector<> unterstützen will.

    Der C++ Standard legt genau fest, welche Argumente die Standard Container haben.

    Wenigstens das. So sieht denn auch mein Workaround aus - den Allokator aufzählen ist zwar häßlich, aber es funktioniert; und für die Situation, wo string und vector möglich waren, war es tatsächlich einfacher, einen gewöhnlichen Templateparameter zu übergeben.

    Kellerautomat schrieb:

    template <typename...> class ContT
    

    Wenn VC++ und C++Builder nur variadic templates könnten.



  • Welchen Sinn hat das ganze überhaupt, wenn du das Template eh direkt wieder instanziierst. Lass dir doch nen normalen Typen geben, und wenn du unbedingt willst dass keine Konvertierung durchgeführt wird, frage static_assert oder enable_if.



  • audacia schrieb:

    Ich habe einigen Code, der sowas macht:

    template <typename T, template <typename T> class ContT>  
        static void pushBackOrFree (ContT<T*>& cont, T* value);
    

    Was du hättest schreiben sollen:

    template <typename T, class Cont>  
        static void pushBackOrFree (Cont& cont, T* value);
    


  • audacia schrieb:

    dot schrieb:

    Da gibt es nicht zu beheben. Bei template template Parametern musst du eine passende Argumentliste angeben.

    Wunderbar - aber das hilft mir nichts, wenn ich std::basic_string<> und std::vector<> unterstützen will.

    Wieso genau muss es eigentlich ein template template Parameter sein?



  • krümelkacker schrieb:

    audacia schrieb:

    Ich habe einigen Code, der sowas macht:

    template <typename T, template <typename T> class ContT>  
        static void pushBackOrFree (ContT<T*>& cont, T* value);
    

    Was du hättest schreiben sollen:

    template <typename T, class Cont>  
        static void pushBackOrFree (Cont& cont, T* value);
    

    Das wäre schon hier nicht mehr ausreichend gewesen:

    template <typename T, template <typename T> class ContT>  
        static void destroy(ContT<T*>& cont)
    {
        for (ContT<T*>::iterator i = cont.begin (), e = cont.end (); i != e; ++i)
            i->~T ();
    }
    

    Andererseits, vielleicht hätte ich

    template <typename T, template Cont>
        static void destroy(Cont& cont)
    {
        for (Cont::iterator i = cont.begin (), e = cont.end (); i != e; ++i)
            i->~Cont::value_type ();
    }
    

    schreiben können. Werde ich mal probieren.

    dot schrieb:

    Wieso genau muss es eigentlich ein template template Parameter sein?

    Das war in einem anderen Fall, da fand ich es eleganter,

    MyTrie<char, PayloadType, std::basic_string>
    MyTrie<std::string, PayLoadType, std::vector>
    

    schreiben zu können anstelle von

    MyTrie<char, PayloadType, std::string>
    MyTrie<std::string, PayLoadType, std::vector<std::string> >
    

    .


Anmelden zum Antworten