【问题标题】:How to find maximum value in parameter pack?如何在参数包中找到最大值?
【发布时间】:2019-08-25 09:39:37
【问题描述】:

这是一个问题示例:常量变量的模板应根据参数扩展其类型。虽然直接的方式是可能的,但通过给出类型的大小或基础类型名,它很容易出错。

#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;
}

想法是实现模板数据类型,它将返回type,它是无符号整数,至少是参数包中最大值的大小。这也将允许检查模板参数是否正常。

【问题讨论】:

    标签: c++ c++17 variadic-templates


    【解决方案1】:

    在 C++17 中非常简单。我们可以通过简单的std::max (the initializer list overload is constexpr since C++14) 调用来计算最大值。

    我们需要将结果插入一个将大小映射到整数类型的实用程序中,但现在编写起来相当简单:

    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());
    };
    

    然后,将其用于您的原始示例:

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

    我没有美化演员阵容,但也可以编写一个实用程序来实现这一点。

    你可以see it live

    【讨论】:

    • “美化”是指摆脱typename blah::type 垃圾邮件?我的意思是,这不是 C++03。
    • @Yakk-AdamNevraumont - 是的
    • 这可能更简单,因为boost 的库类型可以执行您对type_calculator 所做的选择。但我显然遇到了 max() 技巧的可移植性。我必须研究可行的实现。
    • 考虑允许 no 位。在BITS 中使用BIT 会简化事情。
    【解决方案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);
    

    现在我们可以得到:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-22
      • 2021-02-10
      • 2021-03-15
      • 1970-01-01
      • 2023-03-13
      相关资源
      最近更新 更多