http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51199
Bug #: 51199 Summary: [C++11][DR 547] gcc forms impossible types derived from function types with cv-qualifier-seq Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: daniel.krueg...@googlemail.com CC: ja...@gcc.gnu.org gcc 4.7 20111112 (experimental) in C++11 mode accepts the following code: //------ typedef void FC() const; template<class T> struct add_ref { typedef T& type; }; typedef add_ref<FC>::type ref_type; // #1 template<class T> struct add_ptr { typedef T* type; }; typedef add_ptr<FC>::type ptr_type; // #2 //------ According to DR 547 the function type FC is valid as argument for the templates add_ref and add_ptr and shall keep its cv-qualifier-seq, but the type declarations ref_type (#1) and ptr_type (#2) are accepted, even though they describe types that are impossible to form in C++ because they contradict what the bulleted list in N3290 8.3.5 p6 allows. Further-on 8.3.5 p10 say: "A typedef of a function type whose declarator includes a cv-qualifier-seq shall be used only to declare the function type for a non-static member function, to declare the function type to which a pointer to member refers, or to declare the top-level function type of another function typedef declaration." Nonetheless static deduction can be used to demonstrate that ref_type behaves essentially like the type void (&FC)() const and that ptr_type behaves like the type void (*FC)() const. E.g. the following tests succeed given the type definitions FC, ref_type, and ptr_type from above: //-- #include <type_traits> static_assert(std::is_reference<ref_type>::value, "Ouch"); static_assert(std::is_same<std::remove_reference<ref_type>::type, FC>::value, "Ouch"); static_assert(std::is_pointer<ptr_type>::value, "Ouch"); static_assert(std::is_same<std::remove_pointer<ptr_type>::type, FC>::value, "Ouch"); //-- The formation of the types ref_type and ptr_type should be rejected. Additionally, under sfinae conditions, these invalid types are also not properly recognized. The following code is rejected by gcc, but shouldn't: //---- typedef void FC() const; template<class T, class = T&> auto fr(int) -> char; template<class> auto fr(...) -> char (&)[2]; static_assert(sizeof(fr<FC>(0)) == 2, "Error"); template<class T, class = T*> auto fp(int) -> char; template<class> auto fp(...) -> char (&)[2]; static_assert(sizeof(fp<FC>(0)) == 2, "Error"); //---- Both static assertions fail, but shouldn't. If there are doubts about the interpretation of the standard, I would suggest to keep this open, because I have posted a corresponding clarification notice to the CWG reflector and this may end in an issue.