Error saving instance of member function template

I am trying to save a pointer to an instance of a member function template Derived::initializeas follows (see also rextester.com For posterity, I created a simpler version of the problem.):

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

But I get an error in GCC 5.4.0 (and 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()

The problem seems to be related to the argument of the member function template, because it C::template setterImpl<0>works, whereas C::template SetterInterface<0>::Function(which, I suppose, is an alias of the first), does not work. For instance:

Base::setterFunction f1 = &Base::setterImpl<0>;
Base::setterFunction f2 = Base::template SetterInterface<0>::Function;
+4
source share
1 answer

, initialize() non-type-template ; , ; , constexpr ( ++ 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>;
    };
};
+3

Source: https://habr.com/ru/post/1689571/


All Articles