[Bug c++/51199] New: [C++11][DR 547] gcc forms impossible types derived from function types with cv-qualifier-seq
daniel.kruegler at googlemail dot com
gcc-bugzilla@gcc.gnu.org
Fri Nov 18 01:04:00 GMT 2011
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: unassigned@gcc.gnu.org
ReportedBy: daniel.kruegler@googlemail.com
CC: jason@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.
More information about the Gcc-bugs
mailing list