This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/81102] New: G++ wrong error report for partial template specialization


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81102

            Bug ID: 81102
           Summary: G++ wrong error report for partial template
                    specialization
           Product: gcc
           Version: 7.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: boite.pour.spam at gmail dot com
  Target Milestone: ---

Hi,

 This code used to work fine with G++ version < 7.0:


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

// [...]

// Zero-ary
template <int line, typename Ret, Ret (&Func)()>
struct HelperWrapper<line, Ret (&)(), Func>
{
    static inline void* WrapFuncT(const int)
    {
        return (void*)Func; // Changed for the bug report, normally I capture
the function pointer, and make a list of its arguments type here, and return an
object that's callable and perform argument convertion via variant types.
    }
};

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

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

[...]





Here's a godbolt that shows it starts failing since GCC v7.0.0 :
godbolt.org/g/uW3D7O


The diagnostic is:
<source>:20:8: error: partial specialization 'struct HelperWrapper<line, Ret
(&)(Arg1), Func>' is not more specialized than [-fpermissive]
 struct HelperWrapper<line, Ret (&)(Arg1), Func>
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:5:8: note: primary template 'template<int line, class FuncSig, FuncSig
f> struct HelperWrapper'
 struct HelperWrapper;


IIUC, in the zero-ary case, the primary template argument FuncSig (which should
be matched to "Ret (&)()" does not match the specialized version "Ret" argument
which only match the return type of the function argument.
Thus, there does not exist any type that could lead to ambiguity here.

For the other arity case,  the diagnostic seems wrong too since there is an
additional template argument for the function argument type. That is: it does
not exist a type T that could match the specialized version while matching the
primary template directly, since the type T must "embed" 2 different types:
it's a function + a template  argument type.

Moreover, replacing the (&) part and (&Func) part by (*) and (*Func) makes G++
happy with the code.

The C++ standard allows taking reference on function as it decays to function
pointer, so the initial writing should be allowed without diagnostic.

However this code is used on Microsoft C++ compiler too, and it only accept
(&Func) version and fails compiling (*Func) version (this has been the case
since 2007 IIRC). It's also accepted on Intel C++ compiler too, and on Clang
(check the godbolt.org)

Thus, since G++7.0, I have to make 2 version (one with function pointers and
one with reference to support all compilers) and it's not very clean.
It also fails on G++8.0 beta.

Can you explain if it's a feature (and if yes, what is the reason for making a
difference between function pointer and function reference, and the extract of
the C++ standard that supports this claim) or a bug, please ?

Thank you very much.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]