template definition



  • Hallo zusammen,
    Ich hab ein Problem mit der Definition eines templates.
    Code sagt mehr als tausend Worte, also hier der Code.
    Ich habe keine Schimmer wie ich den return type des template deklarieren muss.

    #include <vector>
    #include <iostream>
    
    template <typename result_container,typename container_type>
    typename result_container<typename container_type::const_iterator>
    makeVectorOfIterators(const container_type &container)
    {
    	typename result_container<typename container_type::const_iterator> result ;
    	for (typename container_type::const_iterator iter=container.begin();iter!=container.end();++iter)
    		result.push_back(iter) ;
    	return result ;
    }
    
    int main()
    {
    	std::vector<int> data ;
    	for (int i=0;i<10;i++)
    		data.push_back(i) ;
    
    	std::vector<std::vector<int>::const_iterator> vectorOfIterators=makeVectorOfIterators<std::vector>(data) ;	
    }
    

    Unter g++ 5.1.0 gibt es folgende Fehler:

    `

    makecontainerWithIterator.cpp:5:10: error: expected nested-name-specifier before 'result_container'

    typename result_container<typename container_type::const_iterator>

          ^
    

    makecontainerWithIterator.cpp:5:26: error: expected initializer before '<' token

    typename result_container<typename container_type::const_iterator>

                          ^
    

    makecontainerWithIterator.cpp: In function 'int main()':

    makecontainerWithIterator.cpp:21:66: error: 'makeVectorOfIterators' was not declared in this scope

    std::vector<std::vector<int>::const_iterator> vectorOfIterators=makeVectorOfIteratorsstd::vector(data) ;

                                                                  ^
    

    makecontainerWithIterator.cpp:21:99: error: missing template arguments before '>' token

    std::vector<std::vector<int>::const_iterator> vectorOfIterators=makeVectorOfIteratorsstd::vector(data) ;

    `


  • Mod

    `makecontainerWithIterator.cpp:5:10: error: expected nested-name-specifier before 'result_container'

    typename result_container<typename container_type::const_iterator> `

    typename ist hier grammatikalisch inkorrekt:

    §14.6/3 schrieb:

    typename-specifier:
    ~ ~ typename nested-name-specifier identifier
    ~ ~ typename nested-name-specifier template opt simple-template-id

    (Die Tilde steht hier für ein Leerzeichen. Seit wann funktioniert &nbsp; nicht mehr?)
    In anderen Worten, der Name dem typename vorangestellt wird muss qualifiziert sein, e.g. A::B oder ::B . In deinem Fall ist das typename jedoch vollkommen überflüssig.

    Dein zweiter Fehler besteht darin, dass du den Zielcontainer mittels eines Typ-Templateparameters nehmen möchtest, dieser jedoch ein Template ist. Du brauchst dementsprechend ein Template-Templateparameter.

    template <template <typename...> class result_container,typename container_type>
    result_container<typename container_type::const_iterator>
    makeVectorOfIterators(const container_type &container)
    

    Übrigens habe ich hier schon mal gezeigt wie dein Code einfacher zu implementieren ist;

    template <template <typename...> class result_container,typename container_type>
    result_container<typename container_type::const_iterator>
    makeVectorOfIterators(const container_type &container)
    {
        result_container<typename container_type::const_iterator> result(container.size());
        std::iota(result.begin(), result.end(), container.begin());
        return result ;
    }
    

    Beispiel.



  • Danke 👍
    Hab verstanden.
    Der zweite Fehler war mir klar.
    Mein Problem war die Definition des templates.



  • Mist zu langsam. Wollte gerade etwas ähnliches schreiben. Allerdings war meine Lösung etwas weniger elegant (keine variadic templates) und ich habe selbst noch eine Frage. Wenn man es ohne variadic templates macht muss man scheinbar einen Default Wert für den Allocator angeben. Nur so compiliert es:

    template <template<typename T, typename = std::allocator<T>> typename result_container, typename container_type>
    

    Wenn ich keinen Default Parameter fürs zweite Argument angebe compiliert es nicht, und wenn ich den zweiten Template Parameter weglasse compiliert es auch nicht. Hast jemand gerade zufällig den Absatz im Standard parat wo steht, dass variadic templates irgendwie Default Werte übernehmen?


  • Mod

    sebi707 schrieb:

    Hast jemand gerade zufällig den Absatz im Standard parat wo steht, dass variadic templates irgendwie Default Werte übernehmen?

    Den gibt es nicht.

    CWG <a href= schrieb:

    #2057">It is not clear how to handle an example like:

    template<typename T1, typename T2 = char> class A { };
    
      template<template<typename... T> class X> class S {
        X<int> x;
      };
    
      S<A> a;
    

    Issue 184 dealt with a similar question but did so in the era before variadic templates. This usage should be permitted in modern C++.



  • Arcoth schrieb:

    Den gibt es nicht.

    Noch nicht oder wie? Jedenfalls funktioniert dein Code mit gcc 4.4, gcc 4.9, clang 3.5 und VS2015. Mehr habe ich jetzt nicht getestet...


  • Mod

    sebi707 schrieb:

    Arcoth schrieb:

    Den gibt es nicht.

    Noch nicht oder wie?

    Jo. Vielleicht wird auch nur ein existierender abgeändert. Vielleicht wird nichts getan, weil das Komitee diesen Defekt für die restliche Zeit seiner Existenz als minderwertig abtut. 😃

    Jedenfalls funktioniert dein Code mit gcc 4.4, gcc 4.9, clang 3.5 und VS2015. Mehr habe ich jetzt nicht getestet...

    Hättest auf Wandbox noch GCC 5.2, Clang 3.6 und HEADs beider Compiler prüfen können. Auf denen klappt es auch. Schließlich schreibt der Standard gar nichts vor, was impliziert, dass Compiler devs, falls sie dieses Problem spezifisch behandeln, das implementieren was wahrscheinlich irgendwann vom Komitee dekretiert wird. Vielleicht gibt's irgendwo noch einen Bug report.


Anmelden zum Antworten