While (re)implementing a simple constexpr map, I wrote this (godbolt):
template <class key_type, class value_type, int N>
class flat_map
{
private:
struct pair
{
key_type key;
value_type value;
};
const pair elements[N];
public:
consteval flat_map(const pair (&arr)[N]) noexcept
: elements(arr) // works on gcc?!
{}
[[nodiscard]] consteval value_type operator[](const key_type key) const
{
for (const pair &elem : elements)
if (elem.key == key)
return elem.value;
throw "Key not found";
}
};
constexpr flat_map<int, char, 3> m = {{
{ 4, 'a' }, { -1, 'b' }, { 42, 'c' }
}};
static_assert(m[4] == 'a');
static_assert(m[-1] == 'b');
static_assert(m[42] == 'c');
int main()
{
return m[4]; // 97=='a'
}
I naively thought to set the private array elements
as const
and initialize it in the constructor; I was using gcc trunk as compiler, and all was seemingly working well.
When I decided to try it with msvc and clang, I had compilation errors: both were complaining about the array initialization requiring a brace-enclosed initializer list.
In hindsight the other compilers aren't particularly wrong, are they? Am I inadvertently using some gcc non standard extensions here?
Ehm, by the way, what would you do to avoid copying the array elements by hand?
const
must be removed for that. – Ciri