https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123379
Bug ID: 123379
Summary: constexpr template for does not work with temporary
std::span
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: ivan.lazaric.gcc at gmail dot com
Target Milestone: ---
Code:
```cpp
#include <print>
#include <span>
constexpr int data[] = {1, 2, 3};
constexpr auto range = std::span(data);
int main() {
template for (constexpr auto el : std::span(data))
std::println("{}", el);
}
```
Expected for it to compile and produce following output on execution:
```
1
2
3
```
Instead this fails to compile with error:
```
/opt/GCC-REFL/include/c++/16.0.0/bits/stl_iterator.h: In function ‘int main()’:
in ‘constexpr’ expansion of ‘(& __for_range )->std::span<const int,
3>::begin()’
/home/ilazaric/repos/ALL/ivl/reflection/example.cpp:8:31:
8 | std::println("{}", el);
| ^
in ‘constexpr’ expansion of ‘__gnu_cxx::__normal_iterator<const int*,
std::span<const int, 3>::__iter_tag>(((const std::span<const int,
3>*)this)->std::span<const int, 3>::_M_ptr)’
/opt/GCC-REFL/include/c++/16.0.0/span:328:16:
328 | { return iterator(this->_M_ptr); }
| ^~~~~~~~~~~~~~~~~~~~~~
/opt/GCC-REFL/include/c++/16.0.0/bits/stl_iterator.h:1059:9: error: the value
of ‘<temporary>’ is not usable in a constant expression
1059 | : _M_current(__i) { }
| ^~~~~~~~~~~~~~~
/home/ilazaric/repos/ALL/ivl/reflection/example.cpp:8:31: note: ‘<temporary>’
was not declared ‘constexpr’
8 | std::println("{}", el);
| ^
In file included from /opt/GCC-REFL/include/c++/16.0.0/format:52:
in ‘constexpr’ expansion of ‘(& __for_range )->std::span<const int, 3>::end()’
/home/ilazaric/repos/ALL/ivl/reflection/example.cpp:8:31:
/opt/GCC-REFL/include/c++/16.0.0/span:333:31: error: the value of ‘<temporary>’
is not usable in a constant expression
333 | { return iterator(this->_M_ptr + this->size()); }
| ~~~~~~^~~~~~
/home/ilazaric/repos/ALL/ivl/reflection/example.cpp:8:31: note: ‘<temporary>’
was not declared ‘constexpr’
8 | std::println("{}", el);
| ^
```
Godbolt example:
https://godbolt.org/z/1nYvcEx33
If instead the std::span was not a temporary:
```cpp
#include <print>
#include <span>
constexpr int data[] = {1, 2, 3};
constexpr auto range = std::span(data);
int main() {
template for (constexpr auto el : range)
std::println("{}", el);
}
```
This successfully compiles and produces expected output.
Godbolt example:
https://godbolt.org/z/qbPM1c7cT
I came across this while exploring the reflection implementation branch.
This comes out naturally from constructs like:
```cpp
template for (constexpr auto member :
define_static_array(nonstatic_data_members_of(^^T))) {
...
}
```
The proposal that introduced define_static_array gives such constructs as
examples:
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3491r3.html#with-expansion-statements
Might be related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101557 ,
unsure