xryl669 xryl669 -4 years ago 93
C++ Question

Partial specialization rejection with function as template argument

Got this code that used to compile fine with previous version of gcc:

template <int line, typename FuncSig, FuncSig f>
struct HelperWrapper;

// [...]

template <int line, typename Ret, Ret (&Func)()>
struct HelperWrapper<line, Ret (&)(), Func>
{
static inline int WrapFuncT(const int)
{
return 0; // Changed
}
};

// Unary
template <int line, typename Ret, typename Arg1, Ret (&Func)(Arg1)>
struct HelperWrapper<line, Ret (&)(Arg1), Func>
{
static inline int WrapFuncT(const int)
{
return 1; // Changed
}
};

// Binary
template <int line, typename Ret, typename Arg1, typename Arg2, Ret (&Func)(Arg1, Arg2)>
struct HelperWrapper<line, Ret (&)(Arg1, Arg2), Func>
{
static inline int WrapFuncT(const int)
{
return 2; // Changed
}
};


Is rejected by GCC 7.1.1 with error:

a.hpp:683:16: error: partial specialization 'struct Type::Implementation::HelperWrapper<line, Ret (&)(), Func>' is not more specialized than [-fpermissive]
struct HelperWrapper<line, Ret (&)(void), Func>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a.hpp:640:16: note: primary template 'template<int line, class FuncSig, FuncSig f> struct Type::Implementation::HelperWrapper'
struct HelperWrapper;
^~~~~~~~~~~~~
a.hpp:695:16: error: partial specialization 'struct Type::Implementation::HelperWrapper<line, Ret (&)(Arg1), Func>' is not more specialized than [-fpermissive]
struct HelperWrapper<line, Ret (&)(Arg1), Func>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a.hpp:640:16: note: primary template 'template<int line, class FuncSig, FuncSig f> struct Type::Implementation::HelperWrapper'
struct HelperWrapper;
^~~~~~~~~~~~~
a.hpp:707:16: error: partial specialization 'struct Type::Implementation::HelperWrapper<line, Ret (&)(Arg1, Arg2), Func>' is not more specialized than [-fpermissive]
struct HelperWrapper<line, Ret (&)(Arg1, Arg2), Func>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a.hpp:640:16: note: primary template 'template<int line, class FuncSig, FuncSig f> struct Type::Implementation::HelperWrapper'
struct HelperWrapper;


I don't understand the message, since what GCC says as the primary template is, as I understand it, a forward declaration of a generic template structure that does not exists anywhere in the code.

The idea of this code is to capture the signature and the argument type of the function passed in.

1) Is GCC right ? (If you think it's not, please cite what supports your claim in the current standard)

2) How do I fix the code so it's accepted by GCC (it's accepted with Clang down to VisualStudio 2003). I can not use C++11.

Answer Source

It seems like a compiler bug but haven't found any reference to this problem on GCC Bugzilla. Nonetheless I tested your code with the recent GCC compilers on Compiler Explorer as you did and using function pointers instead of function references works with GCC 7.1 too. Here is a live demo.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download