代码之家  ›  专栏  ›  技术社区  ›  Olumide

存储成员函数模板实例时出错

  •  4
  • Olumide  · 技术社区  · 8 年前

    我试图存储一个指向成员函数模板实例的指针 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 setterImpl<0> 工作,鉴于 C::template SetterInterface<0>::Function (我想这是前者的别名)不是。例如:

    Base::setterFunction f1 = &Base::setterImpl<0>;
    Base::setterFunction f2 = Base::template SetterInterface<0>::Function;
    
    1 回复  |  直到 8 年前
        1
  •  3
  •   Massimiliano Janes    8 年前

    问题是 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>;
        };
    };