How to find maximum value in parameter pack?

↘锁芯ラ 提交于 2019-12-11 01:54:26

问题


Here is an example of problem: a constant variable's template should expand its type based on parameters. While direct way is possible, by giving size of type, or underlying typename, it's error-prone.

#include <iostream>

template<size_t bit>
constexpr const uint16_t BIT = 1 << bit;

template<size_t... bits>
constexpr const uint16_t BITS = (uint16_t(1 << bits)|...);

int main()
{
    std::cout << BITS<0,1,3,12> << std::endl;
}

Idea is to implement template data type which would return type which is unsigned integer at least of size of greatest value in parameter pack. This also would allow to check if template arguments are sane.


回答1:


Pretty straight forward in C++17. The maximum value we can calculate with a simple invocation of std::max (the initializer list overload is constexpr since C++14).

The result we'll need to plug into a utility that maps sizes to integer types, but that's fairly simple to write now:

template<std::size_t N>
struct size2Type {
    static auto type_calculator() {
        static_assert( N < 64 );
        if constexpr ( N < 8 )
            return uint8_t{};
        else if constexpr ( N < 16 )
            return uint16_t{};
        else if constexpr ( N < 32 )
            return uint32_t{};
        else
            return uint64_t{};
    }

    using type = decltype(type_calculator());
};

Then, putting it to use in your original example:

template<size_t bit>
constexpr typename size2Type<bit>::type BIT = (typename size2Type<bit>::type)(1) << bit;

template<size_t... bits>
constexpr typename size2Type<std::max({std::size_t(0), bits...})>::type BITS = (BIT<bits> | ... | 0);

I didn't prettify the cast, but a utility can be written to accomplish that too.

You can see it live.




回答2:


template<std::size_t bits>
class uint_that_has_bits_helper {
  static auto calculator() {
    // conditionally compile lines based on compiler capabilities:
    if constexpr (bits <= 8) return std::uint8_t{};
    else if constexpr (bits <= 16) return std::uint16_t{};
    else if constexpr (bits <= 32) return std::uint32_t{};
    else if constexpr (bits <= 64) return std::uint64_t{};
    else if constexpr (bits <= 128) return std::uint128_t{};
  }
public:
  using type = declype(calculator());
};
template<std::size_t bits>
using uint_that_has_bits = typename uint_that_has_bits<bits>::type;

template<std::size_t index>
constexpr auto bit = uint_that_has_bits<index+1>(1) << uint_that_has_bits<index+1>(index);

now we can get:

template<std::size_t... index>
constexpr const auto bits = static_cast<uint_that_has_bits< std::max({index...})+1>>(bit<index> | ...);


来源:https://stackoverflow.com/questions/57644896/how-to-find-maximum-value-in-parameter-pack

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!