简体   繁体   English

如何在参数包中找到最大值?

[英]How to find maximum value in parameter pack?

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. 想法是实现模板数据类型,该类型将返回type ,该type是无符号整数,至少是参数包中最大值的大小。 This also would allow to check if template arguments are sane. 这也可以检查模板参数是否合理。

Pretty straight forward in C++17. 在C ++ 17中非常简单。 The maximum value we can calculate with a simple invocation of std::max ( the initializer list overload is constexpr since C++14 ). 我们可以通过简单的std::max调用来计算std::max初始化列表重载是constexpr因为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 . 你可以看到它

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> | ...);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM