Warum compiliert das nicht?



  • Hallo,

    ich habe hier gerade mit einem kleinen Template zu tun, bekomme es aber nicht kompiliert:

    enum SelectedSide
    {
        LEFT_SIDE,
        RIGHT_SIDE
    };
    
    template <bool active>
    class Foo
    {
    public:
        template <SelectedSide side> void bar();
    };
    
    template <SelectedSide side>
    inline
    void Foo<true>::bar() {}
    
    template <SelectedSide side>
    inline
    void Foo<false>::bar() {}
    

    Der Compiler(MinGW) sagt:

    error: no 'void Foo<true>::bar()' member function declared in class 'Foo<true>'|
    error: no 'void Foo<false>::bar()' member function declared in class 'Foo<false>'|

    Hat auch hier (wie so oft) der Compiler recht, oder seht ihr ein Problem mit der Syntax?

    Zum Code: Ich möchte Foo zweimal gemäß "bool active" spezialisieren und jeweils eine Template-Methode "bar" bekommen. Hat das Problem vielleicht mit einer partiellen Template-Spezialisierung zu tun? Ich weiß, dass Funktionen/Methoden das nicht erlauben. Jedoch klingt die Compilermeldung nach etwas anderem.

    MfG, ZenJu


  • Mod

    Du definierst ein Membertemplate für eine bestimmte Spezialisierung des Klassentemplates - zweimal template:

    template<>
    template <SelectedSide side>
    inline
    void Foo<true>::bar() {}
    
    template <>
    template <SelectedSide side>
    inline
    void Foo<false>::bar() {}
    


  • @camper: Klasse! 🙂 Vielen Dank für die schnelle Hilfe!



  • das inline kannst du übrigens weglassen, template funktionen/member sind automatisch inline.



  • das inline kannst du übrigens weglassen, template funktionen/member sind automatisch inline.

    Gilt das allgemein oder nur für gewisse Compiler? Ich würde da gerne sicher sein, bevor ich das inline weglasse. Konnte mit Google leider keine eindeutige Aussage diesbezüglich finden.



  • Inline ist allgemein nur ein Hinweis an den Compiler, den er nicht notwendigerweise befolgen muss. Auf der anderen Seite kann er unter bestimmten Umständen durchaus auch Funktionen inlinen, die nicht als inline gekennzeichnet sind.


  • Mod

    rüdiger schrieb:

    das inline kannst du übrigens weglassen, template funktionen/member sind automatisch inline.

    Ich glaube nicht. Kapitel und Absatz bitte. Man kann inline hier weglassen, aber nicht etwa, weil Foo<..>::bar inline wäre.



  • Ich denke mal rüdiger spricht auf 9.3/2 an und den Umstand, dass template Funktionen oftmals direkt in der Klassendefinition definiert werden, wo sie dann automatisch inline wären. Aber dass templates per se inline sind kann ich auch nirgends finden.



  • und ich denke dass camper sich auf aufweichung der ODR für nicht-vollständig-spezialisierte templates bezieht.

    sie sind also nicht "de juris" automatisch inline, aber "de facto". mit anderen worten: es kommt (bei compilern die auf "inline" als "tip" nicht achten) auf das selbe raus.

    ich denke auch dass rüdiger diese aufweichung der ODR fälschlicherweise als "automatisch inline" versteht.

    @camper: gibt es einen fall, wo die unterscheidung relevant wäre?



  • drakon schrieb:

    Ich denke mal rüdiger spricht auf 9.3/2 an und den Umstand, dass template Funktionen oftmals direkt in der Klassendefinition definiert werden, wo sie dann automatisch inline wären. Aber dass templates per se inline sind kann ich auch nirgends finden.

    aber damit sind sie ja per se inline-kanidaten - was das inline sinnlos macht - noch dazu, da templates ja nicht ggn die ODR-regel verstoßen können...

    bb


  • Mod

    hustbaer schrieb:

    und ich denke dass camper sich auf aufweichung der ODR für nicht-vollständig-spezialisierte templates bezieht.

    Funktionstemplates sind keine Funktionen. Inline-Funktionen dagegen schon, die Besonderheit ist bei diesen zu suchen, da ein Unterschied zu nicht-inline Funktionen besteht.

    hustbaer schrieb:

    @camper: gibt es einen fall, wo die unterscheidung relevant wäre?

    ... so etwas?

    // ÜE 1
    inline void foo() { ... }
    template <typename> void bar() { ... }
    template bar<int>;
    
    // ÜE 2
    inline void foo();
    template <typename> void bar();
    
    void fun()
    {
        foo(); // ODR verletzt
        bar<int>(); // ok
    }
    

    ist praktisch kaum relevant, weil kein Grund besteht, foo in ÜE2 inline zu deklarieren.


Log in to reply