-
Notifications
You must be signed in to change notification settings - Fork 7
Description
Full name of submitter (unless configured in github; will be published with the issue): Jakub Jelinek
Reference (section label): [stmt.expand]
Link to reflector thread (if any):
Issue description:
I've tried to use iterating expansion statement on define_static_array, but it doesn't work.
#ifdef USE_EXPANSION_STMT_AND_DEFINE_STATIC_ARRAY
#include <meta>
#endif
#include <span>
constexpr int arr1[3] = { 1, 2, 3 };
consteval std::span <const int> foo () { return std::span <const int> (arr1); }
void
bar ()
{
#ifdef USE_EXPANSION_STMT_AND_DEFINE_STATIC_ARRAY
template for (constexpr auto m : std::meta::define_static_array (std::vector { 1, 2, 3 }))
;
#elifdef USE_EXPANSION_STMT
template for (constexpr auto m : foo ())
;
#else
static constexpr auto &&range = foo ();
static constexpr auto begin = range.begin ();
static constexpr auto end = range.end ();
static constexpr auto N = [] consteval {
std::ptrdiff_t result = 0;
for (auto i = begin ; i != end ; ++i) ++result;
return result;
}();
static_assert (N == 3);
{
static constexpr auto iter = begin + decltype(begin - begin){std::ptrdiff_t(0)};
constexpr auto m = *iter;
}
{
static constexpr auto iter = begin + decltype(begin - begin){std::ptrdiff_t(1)};
constexpr auto m = *iter;
}
{
static constexpr auto iter = begin + decltype(begin - begin){std::ptrdiff_t(2)};
constexpr auto m = *iter;
}
#endif
}This test includes what I'm trying to make work, something that does the same thing and fails the same way without reflection and finally attempt to desugarize the expansion statement (note, partly pre-CWG3044 as neither GCC nor clang implements full P2686R4 paper and so I can't remove the static keywords just yet.
Anyway, all 3 versions including the desugarized one fail, the desugarized one with both GCC and clang.
The problem is that type of range is deduced as std::span <const int> && and so it refers to non-const lifetime extended temporary and constant evaluation of the rest doesn't work because of that.
For GCC this can be worked around with using (const std::span <const int>) define_static_array (std::vector { 1, 2, 3 }) instead of define_static_array (std::vector { 1, 2, 3 }) or (const std::span <const int>) foo () instead of foo (), but I don't think that is meant to be what users should use when using expansion statements with define_static_array.
For clang the desugarized version compiles if static constexpr auto &&range = foo (); is changed to static constexpr const auto &&range = foo ();, for GCC I think due to a bug doesn't.
Suggested resolution:
So, I wonder if https://eel.is/c++draft/stmt.expand#5.2 shouldn't be changed
constexpr const auto&& range = expansion-initializer;