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

Arthur O'Dwyer <arthur.j.odwyer at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |arthur.j.odwyer at gmail dot 
com

--- Comment #5 from Arthur O'Dwyer <arthur.j.odwyer at gmail dot com> ---
IIUC, the logic here goes as follows:

(1) Everyone's compiler extension currently makes this assertion fail, not
succeed:

  #include <type_traits>
  template<class T> struct is_array : std::false_type {};
  template<class T> struct is_array<T[]> : std::true_type {};
  template<class T, std::size_t N> struct is_array<T[N]> : std::true_type {};
  static_assert(is_array<int[0]>::value, "this assert fails");

(2) Everyone's library is expected to implement `std::is_array` as the moral
equivalent of the partial specializations in (1). No reasonable library would
ever do anything else.

(3) Therefore, everyone's library will claim that int[0] is not an array type:
  static_assert(std::is_array<int[0]>::value, "this assert fails");

(4) The __is_array builtin is provided specifically to speed up std::is_array
(and for no other reason). Therefore, it should give the same answer as (3).
Therefore, __is_array(int[0]) should also report false:
  static_assert(__is_array(int[0]), "this assert fails");

This logic doesn't depend on any abstract reasoning about whether int[0] is
really "an array type" (I think it certainly *is* an array type, FWIW); it
simply depends on observing the extension's behavior in (1) -- and then *not*
claiming that that's a bug we need to fix. If the extension's behavior is
"correct" (i.e. we're not going to change it), then the behavior of
__is_array(T[0]) falls naturally out of that.

Personally, if I were designing the extension today, I would certainly make
T[0] match the partial specialization for T[N] (with N=0). This seems like it
would match users' expectations, and it doesn't seem to break any code that
wasn't already trying to use the extension, except for pathological party
tricks like being able to obfuscate the condition (N >= 1) as
(std::is_array_v<int[N]>). However, *if* the extension's behavior (1) is set in
stone, *then* conclusion (4) follows inexorably.

And since both (1) and (4) are core-language compiler issues, libstdc++ isn't
involved here: it's simply a bug for GCC to provide
partial-specialization-matching behavior as in (1) without also providing
__is_array behavior as in (4).

HOWEVER, here's a big question which I believe Aaron Ballman also raised on
llvm-project#54705: If it's not an array type, then where do we get off calling
it a compound type ( https://eel.is/c++draft/basic#compound-1 ), a literal type
( https://eel.is/c++draft/basic#types.general-10 ), an aggregate (
https://eel.is/c++draft/dcl.init.aggr#1 ), etc?

It certainly would be *simpler* -- if a big upheaval -- for GCC to provide
neither (1) nor (4), i.e. change the specialization-matching behavior to match
__is_array rather than the other way around. Then all the traits would give
consistent answers: int[0] would be a compound type, a literal type, and an
aggregate *because* it was an array type.

Reply via email to