使用函数作为模板参数的部分特化拒绝

时间:2017-06-09 15:35:03

标签: c++ gcc

使用以前版本的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
    }
};

GCC 7.1.1拒绝了错误:

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;

我不理解这条消息,因为正如我所理解的那样,GCC所说的主要模板是一个通用模板结构的前向声明,该结构在任何地方都不存在代码。

此代码的思想是捕获传入函数的签名和参数类型。

1)GCC是对的吗? (如果您认为不是,请在当前标准中引用支持您声明的内容)

2)如何修复代码,以便GCC接受(它已经被Clang下载到VisualStudio 2003中)。我不能使用C ++ 11。

编辑:我终于成功向GCC开发人员报告了此问题,这是一个应该在下一版本中修复的错误。

1 个答案:

答案 0 :(得分:1)

这似乎是一个编译器错误但未在GCC Bugzilla找到任何对此问题的引用。尽管如此,我使用Compiler Explorer上的最新GCC编译器测试了您的代码,并且使用函数指针而不是函数引用也适用于GCC 7.1。这是live demo

如果partial template specialization不比主模板更专业,编译器可能会抱怨。但在这种情况下,GCC是错误的,因为您将operator+(Matrix,DiagonalMatrix)模板参数专门用作函数引用(FuncSig)。更奇怪的事实是编译器不会抱怨函数指针。

此外,问题的原因似乎不是Ret (&)()而是FuncSig模板参数。当我从主模板及其专业化中删除f时,问题就消失了:

f

查看实时演示here