In the following program `#2` is accepts by all compilers but `#1` is rejected. Shouldn't `#2` also be rejected for the same reason. https://godbolt.org/z/sMraETcbx ``` #include <type_traits> template <class Signature> struct Decompose; template <class T> struct Decompose<void(T)> { using Type = T; }; template <class T> using FTDecay = typename Decompose<void(T)>::Type; // static_assert(std::is_same_v<FTDecay<int()&>, int (*)() &>); //#1: all rejects this as expected FTDecay<int()&> x{}; //#2: all accepts this why? ```
[dcl.fct]/10: A function type with a cv-qualifier-seq or a ref-qualifier shall appear only as: -- [...] -- the type-id of a template-argument for a type-parameter So the code should compile.
(In reply to Marek Polacek from comment #1) > So the code should compile. But https://timsong-cpp.github.io/cppwp/n4950/dcl.ptr#4.sentence-2 says: > [Note 1: [...] Forming a function pointer type is ill-formed if the function type has cv-qualifiers or a ref-qualifier; see [dcl.fct]. [...]] And since `FTDecay<int()&>` is `int (*)() &`, this should be ill-formed?
Note that the ref-qualified function type is not directly an argument for a template type parameter (which would be allowed), but it's a function parameter type inside a function declarator. And those do decay to (possibly ill-formed) pointers.