There are the link to related/duplicated question by @Remy Lebeau in comments. And I liked the first answer from it. https://stackoverflow.com/a/53236832/12779369
Here is a more simplified version of it. The main idea is to use constructor with variadic template arguments and deduction guide.
https://godbolt.org/z/ax5s934oq
#include <algorithm>
#include <array>
#include <iostream>
#include <stdexcept>
#include <type_traits>
#include <utility>
template <typename K, typename T, std::size_t Size>
class CustomMap {
public:
using mapped_type = T;
using key_type = K;
using value_type = std::pair<K, T>;
template <typename... U>
constexpr CustomMap(U&&... vals)
: values_{static_cast<value_type>(std::forward<U>(vals))...} {}
constexpr std::size_t size() const { return Size; }
mapped_type const& at(key_type const& key) const {
auto it = std::find_if(values_.begin(), values_.end(),
[&](auto const& v) { return v.first == key; });
if (it == values_.end()) {
throw std::out_of_range("not found");
}
return it->second;
}
private:
std::array<value_type, Size> values_;
};
template <typename K, typename... U>
CustomMap(std::pair<K, U>...)
-> CustomMap<K, std::common_type_t<U...>, sizeof...(U)>;
template <int... Is>
constexpr auto MakeLargeCustomIntMap(std::integer_sequence<int, Is...>) {
return CustomMap{std::pair{Is, 42}...};
}
int main() {
constexpr auto int_map =
CustomMap{std::pair{1, 12}, std::pair{2, 42}, std::pair{3, 412}};
static_assert(int_map.size() == 3);
std::cout << "second: " << int_map.at(2) << std::endl;
// check the map limitations
// 452 leads to compilation error on gcc
constexpr auto limit_map =
MakeLargeCustomIntMap(std::make_integer_sequence<int, 451>());
static_assert(limit_map.size() == 451);
return 0;
}
There are some limitation of course.
You should make some workarounds to make compiler distinguish copy and/or move constructor from the initialization constructor.
And there maybe some limitation to variadic template argument length. In this example I ended up on 451, for bigger values gcc start yealing error:
fatal error: template instantiation depth exceeds maximum of 900 (use '-ftemplate-depth=' to increase the maximum)
Why it's the 451 while the limit is 900 I don't know? It's a topic for different question.