template parameter container



  • Hallo zusammen,
    Ich geb mal etwas Code um mein Problem auf zu zeigen:

    #include <iostream>
    #include <algorithm>
    #include <vector>
    
    #include <boost/bind.hpp>
    
    class SimpleClass
    {
    private:
    	int m_Value1 ;
    	int m_Value2 ;
    public:
    	SimpleClass(int value1,int value2)
    	:m_Value1(value1),m_Value2(value2)
    	{}
    	bool isValue(int x) const
    	{
    		return x==m_Value1 ;
    	}
    };
    
    template <template <typename> class container_type>
    void do_something(typename container_type<SimpleClass>::iterator begin,typename container_type<SimpleClass>::iterator end) 
    {
    	std::find_if(begin,end,boost::bind(&SimpleClass::isValue,_1,100)) ;		
    }
    
    int main()
    {
    	std::vector<SimpleClass> data ;
    	data.push_back(SimpleClass(10,29)) ;
    	data.push_back(SimpleClass(100,28)) ;
    	data.push_back(SimpleClass(11,22)) ;
    	data.push_back(SimpleClass(13,21)) ;
    
    	do_something(data.begin(),data.end()) ;
    }
    

    Der GCC spuckt folgende Fehlermeldung:

    container_as_template.cpp: In function 'int main()':
    container_as_template.cpp:37:38: error: no matching function for call to 'do_something(std::vector<SimpleClass>::iterator, std::vector<SimpleClass>::iterator)'
    do_something(data.begin(),data.end()) ;
    ^
    container_as_template.cpp:37:38: note: candidate is:
    container_as_template.cpp:23:6: note: template<template<class> class container_type> void do_something(typename container_type<SimpleClass>::const_iterator, typename container_type<SimpleClass>::const_iterator)
    void do_something(typename container_type<SimpleClass>::const_iterator begin,typename container_type<SimpleClass>::const_iterator end)
    ^
    container_as_template.cpp:23:6: note: template argument deduction/substitution failed:
    container_as_template.cpp:37:38: note: couldn't deduce template parameter 'template<class> class container_type'
    do_something(data.begin(),data.end()) ;

    Wie müssen bei do_something die template parameter angegeben werden, dass der Compiler das frisst?
    Danke



  • Du musst bei do_something explizit den ContainerTypen angeben, da der Compiler ihn nicht anhand des Iterators deduzieren kann.
    Wenn du nur Container auf deinen Typen zulassen will, mach den Iterator direkt als Templateparameter und nutz enable_if oder static_assert.



  • es müsste eigentlich

    template <typename, typename = std::allocator<SimpleClass>>
    

    heißen oder ähnlich (ähnlich heißt, dass man es dann explizit angibt später, anstatt als default argument, oder als weiterer template parameter, ...).
    STL container haben 2 template params.



  • Es gibt auch Container mit 3 oder 4 Parametern.
    Ich denke es ist besser es so zu machen wie Nathan vorgeschlagen hat und die Iteratoren als Templateparameter zu nehmen.



  • Danke an euch allen, hab das Problem nach Nathan Vorschlag mit static_assert gelöst.


  • Mod

    Gibt's irgendeinen triftigen Grund, nicht template<typename Iterator> ... zu nehmen?


  • Mod

    Wenn du nur Container auf deinen Typen zulassen will, mach den Iterator direkt als Templateparameter und nutz enable_if oder static_assert.

    case schrieb:

    Danke an euch allen, hab das Problem nach Nathan Vorschlag mit static_assert gelöst.


  • Mod

    Ja, das habe ich wohl auch gelesen, ich meine eher den Teil, den du nicht fett markiert hast:

    Wenn du nur Container auf deinen Typen zulassen will,

    Warum? So hat man mehr Aufwand für Code, der weniger kann und den Anwender mehr ärgert.


  • Mod

    Ja, das habe ich wohl auch gelesen, ich meine eher den Teil, den du nicht fett markiert hast:

    Danach hast du doch nicht gefragt? Der TE hat jetzt wahrscheinlich

    template <typename Iter>
    void do_something(Iter begin, Iter end) 
    {
        static_assert( std::is_base_of<SimpleClass, typename std::iterator_traits<Iter>::value_type>{}, "" );
        std::find_if(begin,end,boost::bind(&SimpleClass::isValue,_1,100)) ;     
    }
    

    stehen, was der Form entspricht die du erwähnt hast.

    So hat man mehr Aufwand für Code, der weniger kann und den Anwender mehr ärgert.

    Oder man hat Code der dem Anwender ordentliche Diagnostik mitgibt. Vielleicht hätte er auch enable_if +Kommentar nehmen können.



  • Braunstein schrieb:

    Es gibt auch Container mit 3 oder 4 Parametern.
    Ich denke es ist besser es so zu machen wie Nathan vorgeschlagen hat und die Iteratoren als Templateparameter zu nehmen.

    Wer versucht über stacks zu iterieren?
    Spaß bei Seite: Ich hatte noch überlegt - editiere ich mein Beitrag noch um auf Nathan zu verweisen?

    Oh und bitte erwähne jetzt nicht die Map oder selbstimplementierte Spezielcontainer -.-



  • 5cript schrieb:

    Wer versucht über stacks zu iterieren?
    Spaß bei Seite: Ich hatte noch überlegt - editiere ich mein Beitrag noch um auf Nathan zu verweisen?

    Oh und bitte erwähne jetzt nicht die Map oder selbstimplementierte Spezielcontainer -.-

    Nö, ich erwähne set. 🙂


Anmelden zum Antworten