Spezialisierte template-Methode einer template-Klasse lässt sich nur innerhalb der Klasse (inline) definieren



  • Hallo zusammen,

    ich würde gerne die Definitionen der Methoden meiner template-Klasse nicht innerhalb der Klassendefinition machen sondern außerhalb.
    Jetzt habe ich aber ein Problem mit einer spezialisierten template-Methode - die will sich nämlich nur inline vom Compiler fressen lassen. 😡
    Ich habe das Ganze auf ein kleines Bsp. übertragen. Die template-Funktion-Beispiele (bar()) habe ich eingebaut, um meine Spezialisierungssyntax zu prüfen.

    #include <iostream>
    #include <string>
    
    template< typename t_0 >
    void bar()
    {
       std::cout << "bar" << " " << sizeof( t_0 ) << std::endl;
    }
    
    template<>
    void bar< std::string >()
    {
       std::cout << "bar_spec" << " " << 1887 << std::endl;
    }
    
    template< typename t_0 >
    class t_foo
    {
    public:
       void f0() const;
    
       template< typename t_1 >
       void f1() const;
    
       template<>
       void f1< std::string >() const;
       //{
       //   std::cout << "f1_spec" << " " << sizeof( t_0 ) << " " << 33 << std::endl;
       //}
    
    private:
       t_0 m_0;
    
    };
    
    template< typename t_0 >
    void t_foo< t_0 >::f0() const
    {
       std::cout << "f0" << " " << sizeof( t_0 ) << std::endl;
    }
    
    template< typename t_0 >
    template< typename t_1 >
    void t_foo< t_0 >::f1() const
    {
       std::cout << "f1" << " " << sizeof( t_0 ) << " " << sizeof( t_1 ) << std::endl;
    }
    
    template< typename t_0 >
    template<>
    void t_foo< t_0 >::f1< std::string >() const
    {
       std::cout << "f1_spec" << " " << sizeof( t_0 ) << " " << 33 << std::endl;
    }
    
    int main()
    {
       bar< int >();
       bar< std::string >();
    
       t_foo< int > foo_0;
    
       foo_0.f0();
       foo_0.f1< double >();
       foo_0.f1< std::string >();
    
       std::string dummy;
       std::cin >> dummy;
    }
    

    Das Problem stellt die mit std::string spezialisierte Variante von t_foo::f1() dar.
    Der (Visual Studio 2010-) Compiler sagt dazu Folgendes:

    1>x:\1887\main.cpp(10028): error C2768: 't_foo<t_0>::f1' : illegal use of explicit template arguments
    1>x:\1887\main.cpp(10023): error C3212: 't_foo<t_0>::f1' : an explicit specialization of a template member must be a member of an explicit specialization
    1> x:\1887\main.cpp(10000) : see declaration of 't_foo<t_0>::f1'

    Wenn ich die auskommentierte Inline-Variante verwende, geht es.
    Die Fehlermeldung C3212 deutet ja darauf hin, dass es nicht erlaubt ist. Aber warum? Und warum ist es inline ok?

    Die Erklärung (http://msdn.microsoft.com/en-us/library/b11ck5wk(v=vs.90).aspx) hat mich auch nicht wirklich erleuchtet. Da steht, dass es nicht legal ist, aber warum wird auch nicht klar.



  • n3242 14.7.3/16 schrieb:

    In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well. In such explicit specialization declaration, the keyword template followed by a template-parameter-list shall be provided instead of the template<> preceding the explicit specialization declaration of the member. The types of the template-parameters in the template-parameter-list shall be the same as those specified in the primary template definition. Example:

    template <class T1> class A {
      template<class T2> class B {
        template<class T3> void mf1(T3);
        void mf2();
      };
    };
    template <> template <class X>
    class A<int>::B {
      template <class T> void mf1(T);
    };
    template <> template <> template<class T>
    void A<int>::B<double>::mf1(T t) { }
    template <class Y> template <>
    void A<Y>::B<double>::mf2() { } // ill-formed; B<double> is specialized but
                                    // its enclosing class template A is not
    

    http://ideone.com/vpBhD
    http://ideone.com/jWdcI

    Meinem Verständnis nach dürfte auch Version 1 nicht kompilieren.


  • Mod

    cooky451 schrieb:

    Meinem Verständnis nach dürfte auch Version 1 nicht kompilieren.

    Richtig, da Spezialisierungen grundsätzlich nur auf Namensraumebene deklariert werden können.



  • Hallo,

    vielen Dank ihr zwei für die Antworten.
    Gibt es auch einen Grund, warum das nicht erlaubt ist (außer, dass der Standard dies so festlegt)?


Anmelden zum Antworten