On 21/09/20 12:33 +0200, Florian Weimer via Libstdc++ wrote:
* Alejandro Colomar:

[[
CC += libc-co...@sourceware.org
CC += gcc@gcc.gnu.org
CC += libstd...@gcc.gnu.org
]]

Hi Florian,

On 2020-09-21 10:38, Florian Weimer wrote:
* Alejandro Colomar via Libc-alpha:

I'd like to propose exposing the macro 'array_length()' as defined in
'include/array_length.h' to the user.

It would need a good C++ port, probably one for C++98 and another one
for C++14 or later.

For C++, I use the following definition:


        #include <cassert>
        #include <sys/cdefs.h>
        #include <type_traits>


        #define is_array__(a)   (std::is_array <__typeof__(a)>::value)

Should be decltype.

And it's wrong for references to arrays, it should be
is_array<typename remove_reference<decltype(a)>::type>::value.

However, there are a few problems:

1) This doesn't work for VLAs (GNU extension).
   I couldn't find a way to do it.  Maybe I should file a bug in GCC.

I do not think VLA support is critical.  C++ programmers will be used to
limited support in utility functions.

2) Also, this requires C++11; I don't know how to do it for older C++.
   Again, support from the compiler would be great.

I think limited C++98 support is possible using a function template,
where the array length N is a template parameter.  To enable use in
constant expressions, you can return a type of char[N], and the macro
wrapper should then apply sizeof to the function result.

Right, it's trivial to write in any version of C++:

template<typename T, std::size_t N>
#if __cplusplus >= 201103L
constexpr
#endif
inline std::size_t
array_length(const T(&)[N])
#if __cplusplus >= 201103L
noexcept
#endif
{ return N; }

3) The macro can't be used in the same places as the C version,
   because of the `({})`.
   The `0 * sizeof(struct{...})` trick doesn't work in C++ due to:
        error: types may not be defined in 'sizeof' expressions

For C++11, you can use a constexpr function instead of a macro.

array_length should not be a macro in current C++ modes, so that we
retain compatibility if a future C++ standard adds array_length (or
nitems) on its own.  This is not a concern for legacy C++98 mode.

A macro is 100% unacceptable for C++.

This function already exists anyway, see std::size:
https://en.cppreference.com/w/cpp/iterator/size



Reply via email to