2017-11-20 5 views
4

멤버 함수 템플릿 Derived::initialize의 인스턴스에 대한 포인터를 저장하려고합니다 (rextester.com 참조). 후손을 위해 simpler version을 생성했습니다.) :멤버 함수 템플릿의 인스턴스를 저장하는 중 오류가 발생했습니다.

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); 
} 

하지만 GCC 5.4.0 (그리고 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() 

문제는 멤버 함수 템플릿 인수로 거짓말을 나타납니다 때문에 C::template SetterInterface<0>::Function 반면 C::template setterImpl<0> 작업 (WH 나는 이전에 대한 별명으로 생각한다). 예를 들어

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

초기화() 비 형식 템플릿 매개 변수는 상수 표현되어야한다; 귀하의 코드에서 그것은 정적 멤버 대신, 그래서 그것은 작동하지 않을 수 있습니다; 정적 인 constexpr로 선언했다면 그렇게 할 수 있습니다. 어쨌든, 당신은 무엇을 성취하려고합니까? –

답변

3

문제는 initialize()비 형 템플릿 파라미터 일정한 표현되어야한다는 것이다; 귀하의 코드에서 그것은 정적 멤버 대신, 그래서 그것은 작동하지 않을 수 있습니다; 이 수, 당신은 정적 constexpr로 선언 (하지만 당신은 적어도 C++ (11) 다음 컴파일러 필요할 것) 경우 :

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

불행히도 저는 C++ 98/03로 제한됩니다. 이것을 나타 내기 위해 질문 태그를 수정하고 있습니다. – Olumide

+0

@olumide 그대로, 원하는 것은 C++ 03에서는 불가능한 것처럼 보입니다. 그렇다면 setterImpl을 직접 전달하는 것이 어떻습니까? –

+0

'setterImpl'이'Derived'가 상속하는 다른 기본 클래스 (표시되지 않음)에서 다른 이름을 갖고 있기 때문에 그럴 수 없습니다. 그러므로'SetterInterface :: Function'는 이들 멤버 함수에 대한 일반적인 이름을 만들려고 시도합니다. – Olumide