79678808

Date: 2025-06-25 09:45:22
Score: 1.5
Natty:
Report link

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.

Reasons:
  • Blacklisted phrase (1): stackoverflow
  • Long answer (-1):
  • Has code block (-0.5):
  • Contains question mark (0.5):
  • User mentioned (1): @Remy
  • Low reputation (0.5):
Posted by: bugdruhman