Repository navigation
[C API] Py_ARRAY_LENGTH() macro is incompatible with g++ -std=gnu++11 #158810
Description
Activity
- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Oct 4, 2026 - changed the title
[-]C API: Py_ARRAY_LENGTH() macro is incompatible with g++ -std=gnu++11[/-][+][C API] Py_ARRAY_LENGTH() macro is incompatible with g++ -std=gnu++11[/+]on Oct 4, 2026 The documentation for
__builtin_types_compatible_psaysNote: This construct is only available for C.
Which leaves a mystery about why it seems to work in
-std=c++11but which does imply you shouldn't be using it in c++- added a commit that references this issue
on Oct 4, 2026 @da-woods: It would be nice to be able to use
__builtin_types_compatible_p()on C++ when it's supported. The problem is that I don't know how to check if the built-in function is available or not.(...) which does imply you shouldn't be using it in c++
Well well well, a simple fix is to do exactly that: don't use
__builtin_types_compatible_p()on C++. I implemented this approach in PR gh-158812.Other places in the code base use
_Py__has_builtin, but I don't think this buys us much here, since we know__builtin_types_compatible_pisn't supported in C++. Yet, it'll reduce the detection to#if _Py__has_builtin(__builtin_types_compatible_p).The most natural fit in modern C++ beginning with C++17 is std::size, and AI will for sure spit out something for earlier versions, but that's all template based, and you've mentioned in #157649 (comment) that templates did not play out nicely for
Py_CLEARet al.- addedinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)buildThe build process and cross-buildThe build process and cross-build
on Oct 5, 2026 - added a commit that references this issue
on Oct 5, 2026 The example builds correctly if I use -std=c++11 (g++ -std=c++11 example.cpp).
When using
-std=c++11, the__STRICT_ANSI__macro is defined. In this case,Py_ARRAY_LENGTH()doesn't use built-in functions (it doesn't use__builtin_types_compatible_p()ortypeof()).Other places in the code base use _Py__has_builtin, but I don't think this buys us much here, since we know __builtin_types_compatible_p isn't supported in C++. Yet, it'll reduce the detection to #if _Py__has_builtin(__builtin_types_compatible_p).
__has_builtin(typeof)and__has_builtin(__builtin_types_compatible_p)are false using-std=c++11and-std=gnu++11. So it cannot be used in C++ for Py_ARRAY_LENGTH().The most natural fit in modern C++ beginning with C++17 is std::size, and AI will for sure spit out something for earlier versions, but that's all template based, and you've mentioned in #157649 (comment) that templates did not play out nicely for Py_CLEAR et al.
I'm sure that it's possible to write something nice using templates, but I would prefer to keep the Python C API simple, and avoid C++ templates in general.
#define Py_ARRAY_LENGTH(array) (sizeof(array) / sizeof((array)[0]))works just fine on C++.It's just that it doesn't detect API misuse on C++. It would be nice to have, but it's ok to not detect API misuse in this case.
I just merged my PR to just use
#define Py_ARRAY_LENGTH(array) (sizeof(array) / sizeof((array)[0]))in C++.Thanks for your feedback @da-woods and @chris-eibl.
Reacted by Chris EiblReacted by Chris Eibl- added a commit that references this issue
on Oct 6, 2026
Bug report
Example:
Building this example with
g++ -std=gnu++11 example.cppor justg++ example.cppfails with:The example builds correctly if I use
-std=c++11(g++ -std=c++11 example.cpp).The macro is currently defined as:
I'm not sure why
__builtin_types_compatible_p()is available with-std=c++11, but not with-std=gnu++11.I made my tests using g++ (GCC) 16.2.1 on Fedora 44.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs