以函数作为模板参数的部分专业化拒绝 [英] Partial specialization rejection with function as template argument

查看:173
本文介绍了以函数作为模板参数的部分专业化拒绝的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 模板< int line,typename FuncSig, FuncSig f> 
struct HelperWrapper;
$ b // //

模板< int line,typename Ret,Ret(& Func)()>
struct HelperWrapper< line,Ret(&)(),Func>
{
static inline int WrapFuncT(const int)
{
return 0; //更改
}
};

//一元
模板< int line,typename Ret,typename Arg1,Ret(& Func)(Arg1)>
struct HelperWrapper< line,Ret(&)(Arg1),Func>
{
static inline int WrapFuncT(const int)
{
return 1; //更改
}
};
$ b $ // Binary
模板< 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; //更改
}
};

被GCC 7.1.1拒绝并出错:

  a.hpp:683:16:error:partial specialization'struct Type :: Implementation :: HelperWrapper< line,Ret(&)(),Func>'is not比[-fpermissive]更专业
struct HelperWrapper< line,Ret(&)(void),Func>
~~~~~~~~~~~~~~~~~~~ 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>不是专用于[-fpermissive]
struct HelperWrapper< line,Ret(&)(Arg1),Func>
~~~~~~~~~~~~~~~~~~~ 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>不是专用于[-fpermissive]
struct HelperWrapper< line,Ret(&)(Arg1,Arg2),Func>
^〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
.http:640:16:note:主要模板'template< int line,class FuncSig,FuncSig f> struct Type :: Implementation :: HelperWrapper'
struct HelperWrapper;

我不明白这个消息,因为GCC认为是主要模板,据我了解它是一种通用模板结构的前向声明,它不存在于代码中的任何地方。



这段代码的想法是捕获签名和传入的函数的参数类型。



<1> GCC是正确的吗? (如果您认为不是,请引用支持您当前标准的声明)



2)如何修复代码,以便GCC接受它(它已被接受铿锵声到VisualStudio 2003)。我无法使用C ++ 11。



编辑:我最终成功地向GCC开发者报告了这个错误,它应该修复下一个版本。

解决方案

它似乎是一个编译器错误,但没有在 GCC Bugzilla 。尽管如此,我仍然使用最新的GCC编译器在编译器资源管理器上测试您的代码,并使用函数指针代替函数引用也适用于GCC 7.1。这是现场演示






如果部分模板专业化并不比主模板更专业。但在这种情况下,GCC是错误的,因为您将 FuncSig 模板参数作为函数引用( Ret(&)())。更奇怪的事实是,编译器不会抱怨函数指针。



此外,问题的原因似乎不是 FuncSig

code>但是 f 模板参数。当我从主模板和专业版中删除 f 时,问题消失:

  template< int line,typename FuncSig> 
struct HelperWrapper;

模板< int line,typename Ret>
struct HelperWrapper< line,Ret(&)()> {
static inline int WrapFuncT(const int){
return 0;
}
};

/ * ... * /

观看现场演示 here


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.

Edit: I finally succeed reporting this to GCC developers and it's a bug that should be fixed in next versions.

解决方案

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.


The compiler might complain if the partial template specialization is not more specialized than the primary template. But in this case GCC is wrong because you specialized the FuncSig template parameter as a function reference (Ret (&)()). The more strange fact is that the compiler doesn't complain for function pointers.

Moreover the cause of the problem seems that not the FuncSig but the f template parameter. When I removed the f from primary template and from its specializations the problem disappeared:

template <int line, typename FuncSig>
struct HelperWrapper;

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

/* ... */

See the live demo here.

这篇关于以函数作为模板参数的部分专业化拒绝的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆