'is_copy_constructible_v<const void*[N]> yields true on GCC since c++20

As mentioned in title:

#include <type_traits>

int main() {
  using Ptr = const void*;
  using Arr = Ptr[3];

  // gcc:   passed since c++20
  // clang: failed
  static_assert(std::is_copy_constructible_v<Arr>);

}

https://godbolt.org/z/enKre9fxr

Have something changed in c++20 that results in this behavior?

I also found this bug report was marked invalid because

This is behaving as specified.

const void* const a[10];
const void* const b[10](a);

is valid code in C++20; it initializes b[0] with &a[0] converted to a const void*, and the rest of b with null pointers.

The void* case is

void* const a[10];
void* const b[10](a);

which is invalid because &a[0] is a void* const*; converting that to void* is not allowed because it casts away constness.

Then I tried this https://godbolt.org/z/zvTr4orvd. However GCC failed to compile b(a). b{a} is okey but I think that it's not a copy-construction but a list-initialization. Am I wrong?

#include <cstdio>
#include <type_traits>

int main() {
  using Ptr = const void*;
  using Arr = Ptr[3];

  // gcc:   failed in c++17 but passed in c++20 
  // clang: failed in c++17 and c++20
  static_assert(std::is_copy_constructible_v<Arr>);

  Arr a = {"a", "b", "c"};

  // gcc & clang error: array initializer must be a brace-enclosed initializer list
  // Arr b = a;
  // Arr b(a);
  
  // gcc & clang ok: equivalent to `c = {&a[0]}`
  Arr c{a};

  for (int i = 0; i < 3; ++i)
    std::printf("%p %p\n", a[i], c[i]);
  std::printf("%p\n", (void*)&a[0]);
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source