How can I get a constexpr
size
from a std::set
, which I can use to return a std::array
with the number of elements in the std::set
in C++23 or to-be C++26, as far as supported by either G++
oder Clang
?
The use-case is a constexpr
parser, which returns a “complex” object, having a flexible number of elements of various kinds in it.
I saw Can I make a constexpr object of std::set?, which seemed to go in a similar direction, but I replaced std::set
already by frozen::set
in the return value.
However, somehow I have to determine the size parameter of it.
frozen
BTW is from https://github.com/serge-sans-paille/frozen .
Because std::set
does not have a constexpr
size
method, I tried to put a std::vector
in between, which apparently does not help.
I have some simplified code:
#include <algorithm>
#include <array>
#include <set>
#include <string_view>
#include <vector>
#include <frozen/set.h>
#include <frozen/bits/basic_types.h>
using namespace std::string_view_literals;
constexpr auto test(const std::string_view input) {
std::set<std::string_view> my_set;
my_set.emplace(input); // For sure the reality is more complicated and can lead to a flexible number of elements
constexpr std::vector<std::string_view> my_vec(my_set.begin(), my_set.end());
constexpr std::array<std::string_view, my_vec.size()> my_arr{};
std::copy_n(my_vec.begin(), my_vec.size(), my_arr.begin());
constexpr frozen::bits::carray<std::string_view, my_vec.size()> my_carr(my_arr);
return frozen::set<std::string_view, my_vec.size()>(my_carr);
}
int main() {
constexpr auto frozen_set = test("test"sv);
return 0;
}
Even when I use a development version of G++ (14.0.1), I get the following error:
test.cpp: In function ‘constexpr auto test(std::string_view)’:
test.cpp:14:68: error: temporary of non-literal type ‘std::set<std::basic_string_view<char> >::iterator’ {aka ‘std::_Rb_tree<std::basic_string_view<char>, std::basic_string_view<char>, std::_Identity<std::basic_string_view<char> >, std::less<std::basic_string_view<char> >, std::allocator<std::basic_string_view<char> > >::const_iterator’} in a constant expression
14 | constexpr std::vector<std::string_view> my_vec(my_set.begin(), my_set.end());
| ~~~~~~~~~~~~^~
In file included from /usr/include/c++/14/set:62,
from test.cpp:3:
/usr/include/c++/14/bits/stl_tree.h:324:12: note: ‘std::_Rb_tree_const_iterator<std::basic_string_view<char> >’ is not literal because:
324 | struct _Rb_tree_const_iterator
| ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/14/bits/stl_tree.h:324:12: note: ‘std::_Rb_tree_const_iterator<std::basic_string_view<char> >’ is not an aggregate, does not have a trivial default constructor, and has no ‘constexpr’ constructor that is not a copy or move constructor
test.cpp:16:59: error: request for member ‘begin’ in ‘my_arr’, which is of non-class type ‘const int’
16 | std::copy_n(my_vec.begin(), my_vec.size(), my_arr.begin());
| ^~~~~
If the error in line 14 is resolved, probably I get the rest done myself.