2017-11-20 2 views
4

ich einen Zeiger auf eine Instanz der Elementfunktion Vorlage zu speichern, ich versuche Derived::initialize wie folgt (siehe auch rextester.com Für die Nachwelt habe ich ein simpler version des Problems geschaffen..):Fehler beim Speichern der Instanz von Elementfunktion Vorlage

class Base 
{ 
public: 
    typedef void (Base::*setterFunction)(unsigned); 

    template<unsigned N> 
    struct SetterInterface 
    { 
     static Base::setterFunction Function; 
    }; 

protected: 
    template<unsigned N> 
    void setterImpl(unsigned) 
    { 
    } 
}; 

template<unsigned N> 
Base::setterFunction Base::SetterInterface<N>::Function = &Base::setterImpl<N>; 

class Derived : public Base 
{ 
public: 
    typedef void (Derived::*Initializer)(); 

    template<typename T , void (T::*F)(unsigned) > 
    void initialize() 
    { 
    } 

    template<typename C> 
    Derived(C*) 
    { 
     Initializer initializer = &Derived::initialize<C, C::template SetterInterface<0>::Function>; // NOT OK 
     //Initializer initializer = &Derived::initialize<C, C::template setterImpl<0> >; // OK 
    } 
}; 

int main() 
{ 
    Derived derived((Base*)0); 
} 

Aber ich bin immer die Fehlermeldung auf GCC 5.4.0 (und 6.4.0)

Test.cpp: In instantiation of ‘Derived::Derived(C*) [with C = Base]’: 
Test.cpp:45:28: required from here 
Test.cpp:37:39: error: no matches converting function ‘initialize’ to type ‘Derived::Initializer {aka void (class Derived::*)()}’ 
    Initializer initializer = &Derived::initialize<C, C::template SetterInterface<0>::Function>; 
            ^
Test.cpp:30:7: note: candidate is: template<class T, void (T::* F1)(unsigned int)> void Derived::initialize() 
    void initialize() 

Das Problem scheint mit dem Member-Funktion Template-Argumente zu liegen, weil C::template setterImpl<0> Arbeiten während C::template SetterInterface<0>::Function (wh Ich nehme an, ein Alias ​​für den ehemaligen zu sein) nicht. Zum Beispiel:

Base::setterFunction f1 = &Base::setterImpl<0>; 
Base::setterFunction f2 = Base::template SetterInterface<0>::Function; 
+2

initialize() nicht Typ Template-Parameter ein konstanter Ausdruck sein sollte; in deinem Code ist es stattdessen ein statisches Member, also kann es nicht funktionieren; es könnte, wenn Sie es als statisch constexpr deklariert haben; Wie auch immer, was versuchst du zu erreichen? –

Antwort

3

Das Problem ist, dass initialize()Nicht-Typ-Template-Parameter sollte ein konstanter Ausdruck sein; in deinem Code ist es stattdessen ein statisches Member, also kann es nicht funktionieren; es könnte, wenn man es als statische constexpr erklärt (aber Sie würden mindestens einen C++ 11-Compiler müssen dann):

class Base 
{ 
protected: 
    template<unsigned N> 
    void setterImpl(unsigned); 
public: 
    typedef void (Base::*setterFunction)(unsigned); 

    template<unsigned N> 
    struct SetterInterface 
    { 
     static constexpr Base::setterFunction Function = &Base::setterImpl<N>; 
    }; 
}; 
+0

Leider bin ich auf C++ 98/03 beschränkt. Ich ändere das Frage-Tag, um dies anzuzeigen. – Olumide

+0

@olumide wie es ist, was Sie wollen, scheint nicht möglich in C++ 03; Das heißt, warum übergeben Sie SetterImpl nicht direkt? –

+0

Ich kann nicht, weil 'setterImpl' in den anderen Basisklassen (nicht gezeigt), die' Derived' erbt, einen anderen Namen hat. Daher versucht 'SetterInterface :: Function' einen generischen Namen für diese Memberfunktionen zu erstellen. – Olumide

Verwandte Themen