#include <cstdio>
#include <array>
#include <cstdint>
#include <utility>
#include <limits>

namespace detail {
constexpr std::uint8_t popcnt_8(std::uint8_t number) {
    number -= ((number >> 1) & 0x55);
    number = (number & 0x33) + ((number >> 2) & 0x33);
    return ((number + (number >> 4)) & 0x0F);
}

template<std::size_t... Indices>
constexpr std::array<std::uint8_t, sizeof...(Indices)>
make_lookup_impl(std::index_sequence<Indices...>) {
    return { popcnt_8(Indices)... };
}
} /* detail */

constexpr decltype(auto) make_lookup() {
    constexpr std::size_t uint8_max = std::numeric_limits<std::uint8_t>::max();
    return detail::make_lookup_impl(std::make_index_sequence<uint8_max + 1>{});
}

int main() {
    const auto lookup = make_lookup();
    const auto test = std::numeric_limits<std::uint64_t>::max();
    
    std::size_t popcount = 0;
    for(std::size_t i = 0; i < sizeof(test); ++i)
        popcount += lookup.at(*(reinterpret_cast<const std::uint8_t*>(&test) + i));

    printf("-- %d\n", popcount);
}