如何在参数包中找到最大值?
How to find maximum value in parameter pack?
这是一个问题示例:常量变量的模板应根据参数扩展其类型。虽然直接的方式是可能的,但通过给出类型的大小或底层类型名称,它很容易出错。
#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;
}
想法是实现模板数据类型 return type
至少是参数包中最大值大小的无符号整数。这也将允许检查模板参数是否正常。
在 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.
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> | ...);
这是一个问题示例:常量变量的模板应根据参数扩展其类型。虽然直接的方式是可能的,但通过给出类型的大小或底层类型名称,它很容易出错。
#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;
}
想法是实现模板数据类型 return type
至少是参数包中最大值大小的无符号整数。这也将允许检查模板参数是否正常。
在 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.
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> | ...);