klassentemplate partiell spezialisieren



  • hi^^

    geht so was mit C++ nicht:

    template<typename T, typename U>
    struct X
    {
    	template<typename A>
    	X(A i, A e);
    };
    
    template<typename T>
    template<typename A>
    X<T, int>::X(A i, A e)
    {}
    
    int main()
    {}
    

    ?

    msvc schrieb:

    `error C3860: template argument list following class template name must list parameters in the order used in template parameter list

    error C2976: 'X<T,U>' : too few template arguments`

    wie hab ich denn die fehlermeldung an sich schon zu verstehen?

    Falls es wirklich nicht geht - wie sähe der workaround aus?

    danke scho mal,
    bb



  • gcc meckert, daß die klasse X<T, int> noch nicht definiert ist.

    das da compiliert

    template<typename T, typename U>
    struct X
    {
        template<typename A>
        X(A i, A e);
    };
    template<typename T>
    struct X<T,int>
    {
        template<typename A>
        X(A i, A e);
    };
    
    template<typename T>
    template<typename A>
    X<T, int>::X(A i, A e)
    {}
    
    int main()
    {}
    


  • hmm.. das compiliert der msvc auch...

    aber das stinkt doch - da muss ich ja scho wieder voll viel mehr schreiben (entweder den code kopieren, der immer gleich bleibt oder ne basis-klasse schreiben und von der erben!? -.-)

    Der Hintergrund ist, dass es um Typkonversation geht und bestimmte Fkt. immer da sind, die implemtierung hängt aber vom zweiten Parameter ab

    #include <vector>
    
    enum frequency
    {
    	every
    	, every_second
    /*	...*/
    };
    
    template<typename T, frequency U>
    struct X
    {
    	std::vector<T> tmp;
    	typedef typename std::vector<T>::const_iterator const_iterator;
    
    	template<typename InputIterator>
    	X(InputIterator i, InputIterator e);
    
    	const_iterator begin() const
    	{
    		return tmp.begin();
    	}
    	const_iterator end() const
    	{
    		return tmp.end();
    	}
    };
    
    template<typename T>
    template<typename InputIterator>
    X<T, every>::X(InputIterator i, InputIterator e)
    :  tmp(i, e)
    {}
    
    template<typename T>
    template<typename InputIterator>
    X<T, every_second>::X(InputIterator i, InputIterator e)
    {
      for(; i != e; ++i, ++i)
      {
        tmp.push_back(*i);
      }
    }
    
    int main()
    {
    	std::vector<int> bla(1, 9);
    
    	X<long long, every> x(bla.begin(), bla.end());
    }
    

    mal angenommen, es geht wirklich nicht so, wie ich das will...
    wäre die basisklasse und erben die alternative oder gibts da was tolleres?

    bb



  • unskilled schrieb:

    aber das stinkt doch - da muss ich ja scho wieder voll viel mehr schreiben (entweder den code kopieren, der immer gleich bleibt oder ne basis-klasse schreiben und von der erben!? -.-)

    oder weiterleiten. du wolltest ja eh so eine copy_frequency-funktion basteln.

    template<typename T, frequency U>
    struct X
    {
        std::vector<T> tmp;
        typedef typename std::vector<T>::const_iterator const_iterator;
    
        template<typename InputIterator>
        X(InputIterator i, InputIterator e)
        {
           copy_frequency(i,e,U,back_inserter(tmp));
        }
    


  • Aber so ist es doch genau noch so!?
    Ich habe wieder ein äußeres template, was ich partiell spezialisieren möchte und ein inneres.
    Ne freie Fkt kommt auch nich in Frage, weil man die nicht partiell spezialisieren kann!?

    ich nahm mal an, du meinst so was hier:

    #include <iterator>
    #include <vector>
    
    enum frequency
    {
    	every
    	, every_second
    /*	...*/
    };
    
    template<typename T, frequency U>
    struct X
    {
    	std::vector<T> tmp;
    	typedef typename std::vector<T>::const_iterator const_iterator;
    
    	template<typename InputIterator, typename BackInserterIterator>
    	void copy_frequency(InputIterator i, InputIterator e, BackInserterIterator b);
    
    	template<typename InputIterator>
    	X(InputIterator i, InputIterator e)
    	{
    		copy_frequency(i, e, std::back_inserter(tmp));
    	}
    
    	const_iterator begin() const
    	{
    		return tmp.begin();
    	}
    	const_iterator end() const
    	{
    		return tmp.end();
    	}
    };
    
    template<typename T>
    template<typename InputIterator, typename BackInserterIterator>
    void X<T, every>::copy_frequency<InputIterator, BackInserterIterator>(InputIterator i, InputIterator e, BackInserterIterator b)
    {//	lnk-error -> findet die implementierung dieser fkt hier nicht
    	for(; i != e; ++i)
    		*b++ = *i;
    }
    
    template<typename T>
    template<typename InputIterator, typename BackInserterIterator>
    void X<T, every>::copy_frequency(InputIterator i, InputIterator e, BackInserterIterator b)
    {//	selber fehler wie davor (template argument list following class template name must list parameters in the order used in template parameter list)
    	for(; i != e; ++i)
    		*b++ = *i;
    }
    
    #include <algorithm>
    #include <iostream>
    #include <list>
    
    void wait()
    {
    	std::cin.clear();
    	std::cin.ignore(std::cin.rdbuf()->in_avail());
    	std::cin.get();
    }
    
    int main()
    {
    	std::list<int> bla(1, 9);
    
    	X<long long, every> x(bla.begin(), bla.end());
    
    	std::copy(x.begin(), x.end(), std::ostream_iterator<long long>(std::cout, ", "));
    	std::cout << std::endl;
    
    	wait();
    }
    

    aber keine der beiden varianten geht - die fehler stehen als kommentar in den fkt. an sich - hab ich dich falsch verstanden?

    bb



  • unskilled schrieb:

    hab ich dich falsch verstanden?

    Ja, copy_frequency meinte ich als globale Funktion.



  • volkard schrieb:

    unskilled schrieb:

    hab ich dich falsch verstanden?

    Ja, copy_frequency meinte ich als globale Funktion.

    und dann halt nen switch(frequency_value) !?
    (da man fkt. ja noch immer nicht partiell spezialisieren kann)
    sieht für mich aber ein wenig unelegant aus...

    bb



  • Dann mach eine Hilfsklasse die nur copy_frequency als statische Funktion bereitstellt. Die kannst du dann partiell spezialisieren.



  • hustbaer schrieb:

    Dann mach eine Hilfsklasse die nur copy_frequency als statische Funktion bereitstellt. Die kannst du dann partiell spezialisieren.

    jo, so mach ichs jz auch^^ ty ;o)


Anmelden zum Antworten