1

When I tried to compare two types of function arrays, I encountered this strange behavior.

I have test code:

using ArrayOfFunctionsT = int (* [])(int);
ArrayOfFunctionsT functions = {};

std::cout << typeid(decltype(functions)).name() << " vs " << typeid(int (*[0])(int)).name() << "\n";
std::cout << std::is_same<decltype(functions), int (*[0])(int)>::value << "\n";

The result of the execution is:

A0_PFiiE vs A0_PFiiE
0

Currently I'm using gcc 10.2.1. What is the reason for this behavior?

TylerH
  • 20,799
  • 66
  • 75
  • 101
  • 4
    You may not declare an array with zero elements. Either the number of elements must be explicitly specified as a positive value or the initializing list shall be non-empty. – Vlad from Moscow Jun 24 '21 at 19:44
  • No, it's possible. Memory just won't allocate, and sizeof will be 0 – Anton Umnicode Jun 24 '21 at 19:48
  • 4
    I believe zero-length arrays are a nonstandard GNU extension. Turn on `-pedantic` and you'll get a warning. – Nate Eldredge Jun 24 '21 at 19:50
  • I know that `decltype` works with expressions and `is_same` with template parameters. I think `is_same` can't work with expressions like ` int (*[0])(int)` – Ripi2 Jun 24 '21 at 19:53
  • @Anton Umnicode From the C++ Standard "4 An array of unknown size initialized with a brace-enclosed initializer-list containing n initializer-clauses, where n shall be greater than zero, " – Vlad from Moscow Jun 24 '21 at 20:05
  • FYI, this prints `1` with clang: https://godbolt.org/z/v9Yx7aEoj – Ranoiaetep Jun 24 '21 at 20:07
  • @Anton Umnicode So in fact your code is ill-formed. In such cases compilers can behave differently. – Vlad from Moscow Jun 24 '21 at 20:25

1 Answers1

0

Quick answer: zero-sized array are forbidden by C++ standard. So any result that come afterwards are compiler dependent.


In the comment section, people has mentioned that:

is_same can't work with expressions like int (*[0])(int)

However, that's not the reason here, and is_same does work on expression similar to that. You can create a code snippet with similar result from simpler code:

int arr1[] = {};
int arr2[0] = {};

std::cout << typeid(decltype(arr1)).name() << " vs " << typeid(arr2).name() << "\n";
std::cout << std::is_same<decltype(arr1), decltype(arr2)>::value << "\n";

Demo

Once again GCC prints false and Clang prints true.


The problem here is functions is a zero-sized array, which is forbidden by C++ standard. Anything that does compile relies on compiler extensions, so the results are compiler dependent. Turning on -Wpedantic would emit warnings or errors from the code.

More information here: What happens if I define a 0-size array in C/C++?

Ranoiaetep
  • 5,872
  • 1
  • 14
  • 39