| Summary: | spurious error "non-constant condition" when inside a class member | ||
|---|---|---|---|
| Product: | gcc | Reporter: | R. Diez <rdiez-2006> |
| Component: | c++ | Assignee: | Not yet assigned to anyone <unassigned> |
| Status: | RESOLVED DUPLICATE | ||
| Severity: | normal | CC: | mpolacek, ppalka, webrown.cpp |
| Priority: | P3 | Keywords: | rejects-valid |
| Version: | 14.2.0 | ||
| Target Milestone: | --- | ||
| See Also: |
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106650 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118249 |
||
| Host: | Target: | ||
| Build: | Known to work: | ||
| Known to fail: | Last reconfirmed: | ||
| Bug Depends on: | |||
| Bug Blocks: | 55004 | ||
Clang, edg and MSVC all reject it:
<source>:29:18: error: static assertion expression is not an integral constant expression
29 | static_assert( ArrayElemCount( m_array ) == 10 );
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:29:34: note: implicit use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function
29 | static_assert( ArrayElemCount( m_array ) == 10 );
| ^
GCC is correct here.
This works though:
static_assert( std::size( decltype(m_array){} ) == 10 );
even doing:
```
void f(const TestClass *a)
{
// But this fails when checking from inside the class.
static_assert( ArrayElemCount( a->m_array ) == 10 );
}
```
Will fail as `a->m_array ` is NOT a constexpr
BUT `test_instance.m_array` is one as the reference to test_instance is one too.
I just found out some more information on this. C++ is counterintuitive here, as template ArrayElemCount is only actually using type information. This article considers it a language defect: https://www.learncpp.com/cpp-tutorial/stdarray-length-and-indexing/ That article mentions that this C++ language issue has been addressed in C++23 by P2280: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2280r4.html In the meantime, this C++11 implementation should do the trick. It uses a macro as an intermediate step, but I can live with it: https://brnz.org/hbr/?p=1491 So GCC tries to implement p2280r4 (see PR 106650) but maybe not fully after all. Note p2280r4 is considered a fix for a defect too. clang++ implements p2280 and rejects the test the same. I'm still not sure that there is a bug. (In reply to Andrew Pinski from comment #3) > even doing: > ``` > void f(const TestClass *a) > { > > // But this fails when checking from inside the class. > static_assert( ArrayElemCount( a->m_array ) == 10 ); > > } > ``` > > Will fail as `a->m_array ` is NOT a constexpr > BUT `test_instance.m_array` is one as the reference to test_instance is one > too. IIUC the accepted revision of P2280 only allows unknown 'this', not pointers to unknown in general. The original testcase is basically a dup of PR118249, which has recently been fixed for GCC 15, so let's mark this one as a dup *** This bug has been marked as a duplicate of bug 118429 *** swapped the 2 and 4 in the duplicated bug # :). *** This bug has been marked as a duplicate of bug 118249 *** |
I am getting spurious errors "non-constant condition" and "use of 'this' in a constant expression" when retrieving the size of a fixed member array, but only from inside class members. The same expression works fine when outside the class member. This is a demo: #include <cstddef> // This is like "sizeof(arr) / sizeof(arr[0])", but with fancy C++. template <typename T, std::size_t N> constexpr std::size_t ArrayElemCount ( T const (&)[N] ) noexcept { return N; } class TestClass { public: int m_array[ 10 ]; void test_method ( void ) const; }; static TestClass test_instance; // This works when checking from outside the class. static_assert( ArrayElemCount( test_instance.m_array ) == 10 ); void TestClass::test_method ( void ) const { // The traditional method still works from inside the class. static_assert( sizeof( m_array ) / sizeof( m_array[0]) == 10 ); // But this fails when checking from inside the class. static_assert( ArrayElemCount( m_array ) == 10 ); // The compilation errors with GCC 14.2 are: // error: non-constant condition for static assertion // static_assert( ArrayElemCount( m_array ) == 10 ); // ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~ // error: use of 'this' in a constant expression } You can play with it here: https://godbolt.org/z/bYds71fWW