3

I am dealing with some legacy C structures - where we have zero length array. I think it is not valid, but we have to live with it. I was writing a macro, and I want to decay array to pointer type using std::decay.

But if I have a zero length array -

struct data {
   key[0]; <<
};

std::decay<decltype(data::key)> doesnt decay to pointer type. I am using this as a function return type, and it complains -

GCC Error:

error: ‘function’ declared as function returning an array

It works fine if its an array of length >= 1

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
MGH
  • 475
  • 7
  • 19
  • Is it possible to change their source code from `T key[0]` to `T key[]`? – kennytm Apr 12 '17 at 04:01
  • Unfortunately I can't do that. Can we add a T[0] overload for the std::remove_extend and make this work? – MGH Apr 12 '17 at 04:04
  • 3
    `T[0]` are exceptionally odd beasts, because the standard demands that any attempt to form such types in a SFINAE context causes a deduction failure. That means that large swaths of TMP code written to manipulate normal array types simply do not work with them even on implementations supporting such things as an extension. – T.C. Apr 12 '17 at 04:08
  • A naive attempt like this works - `template struct return_type { using type = std::decay_t; }; template struct return_type { using type = std::decay_t; }; template struct return_type { using type = std::decay_t; }; template struct return_type { using type = T *; }; ` And then use it in macro as `return_type` – MGH Apr 12 '17 at 04:14
  • Possible duplicate of http://stackoverflow.com/questions/12750378/template-won-t-infer-size-of-zero-length-array-in-c and http://stackoverflow.com/questions/4288828/zero-length-c-array-binds-to-pointer-type, no solution given from these though. – kennytm Apr 12 '17 at 04:18

1 Answers1

1

We could let the compiler's type checker, instead of template substitution, to do the decay for us:

#include <type_traits>

template <typename T>
T* as_ptr(T* x) { return x; }

template <typename T>
using DecayToPointer = decltype(as_ptr(std::declval<T>()));


int main() {
    static_assert(std::is_same<DecayToPointer<int[0]>, int*>::value, "");
    static_assert(std::is_same<DecayToPointer<int[1]>, int*>::value, "");
    static_assert(std::is_same<DecayToPointer<int[]>, int*>::value, "");
}
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005