将整数模板参数值映射到原始类型

时间:2018-11-26 19:59:45

标签: c++ templates c++17

我想将数字映射到类型。对于此示例,我将创建一个将sizeof()结果映射到带符号原始类型的函数。

我想知道在现代C ++中是否有更好的方法可以做下面的事情,那就是采用模板化的值并将其转换为类型。现在,这可以将大小转换为已知类型,但是我似乎无法在标准库中找到满足我需要的内容。我错过了什么吗?

如果没有,是否有更好的方法来执行此操作或清除此代码?例如,如果将来以某种方式最终我们拥有128位类型,那将不支持该类型。

#include <iostream>
#include <type_traits>

template <size_t S>
static constexpr auto sizeToType() {
    static_assert(S == 1 or S == 2 or S == 4 or S == 8, "Bad type size");

    if constexpr (S == 1)
        return int8_t{};
    else if constexpr (S == 2)
        return int16_t{};
    else if constexpr (S == 4)
        return int32_t{}; 
    else
        return int64_t{};
}

int main() {
    using MY_TYPE = decltype(sizeToType<2>());

    MY_TYPE myType = MY_TYPE(0xFFFFFFFFFFFFFFFEUL);

    std::cout << sizeof(MY_TYPE) << " bytes" << std::endl;
    std::cout << "MY_TYPE(0xFFFFFFFFFFFFFFFEUL) = " << myType << std::endl;
}

输出(按预期):

2 bytes
MY_TYPE(0xFFFFFFFFFFFFFFFEUL) = -2

2 个答案:

答案 0 :(得分:7)

我不会为此使用C ++ 17 if constexpr,而是使用模板特殊化,因为它对我来说更具声明性。

以下内容:

template<size_t S> struct SizeToType {static_assert(S != S, "Wrong size"); };

template<> struct SizeToType<1> { using type = uint8_t; };
template<> struct SizeToType<2> { using type = uint16_t; };
template<> struct SizeToType<4> { using type = uint32_t; };
template<> struct SizeToType<8> { using type = uint64_t; };

template<size_t S>
using SizeToToTypeT = typename SizeToType<S>::type;

添加更多类型只会在此处添加更多专业化(单线)。

答案 1 :(得分:2)

不是一个很好的解决方案...但是只是为了好玩...

我提出了一个类型特征(使用辅助方法并用于选择内部类型),给定一个数字(字节数)和一个类型列表,请选择大于class FilterInserts(beam.DoFn): """ Filter data for inserts """ def process(self, element): if element["action"] == "insert": element['data']['data']['timestamp'] = element['timestamp'] return [{ 'VD': element['data']['data']['VD'], 'pin': element['data']['data']['pin'], 'timestamp': element['data']['data']['timestamp'], 'other': element['data']['data']['other'], 'CDP': element['data']['data']['CDP'], 'dir': element['data']['data']['dir'], 'attr1' : element['data']['data']['attr1'], 'seo' : element['data']['data']['seo'], 'day' : element['data']['data']['day'], 'DP' : element['data']['data']['DP'], 'at' : element['data']['data']['at'], }] 或等于(如果没有这样的类型,则为空)

sizeof()

现在还有另一个template <std::size_t, typename, typename = std::true_type> struct sizeTypeH; template <std::size_t Dim> struct sizeTypeH<Dim, std::tuple<>, std::true_type> { }; // no type found template <std::size_t Dim, typename T0, typename ... Ts> struct sizeTypeH<Dim, std::tuple<T0, Ts...>, std::integral_constant<bool, (sizeof(T0) >= Dim)>> { using type = T0; }; template <std::size_t Dim, typename T0, typename ... Ts> struct sizeTypeH<Dim, std::tuple<T0, Ts...>, std::integral_constant<bool, (sizeof(T0) < Dim)>> : public sizeTypeH<Dim, std::tuple<Ts...>> { }; template <std::size_t Dim, typename ... Ts> struct sizeType : public sizeTypeH<Dim, std::tuple<Ts...>> { }; template <std::size_t Dim, typename ... Ts> using sizeType_t = typename sizeType<Dim, Ts...>::type; ,它接收一个整数,并使用using类型的有序列表将此类型特征称为

intX_t

在我的平台上,我已验证以下template <std::size_t Dim> using intType_t = sizeType_t<Dim, std::int8_t, std::int16_t, std::int32_t, std::int64_t>;

static_assert()

如果明天要引入 using t8 = intType_t<1u>; using t16 = intType_t<2u>; using t32 = intType_t<4u>; using t64 = intType_t<8u>; static_assert( std::is_same<t8, std::int8_t>{}, "!" ); static_assert( std::is_same<t16, std::int16_t>{}, "!" ); static_assert( std::is_same<t32, std::int32_t>{}, "!" ); static_assert( std::is_same<t64, std::int64_t>{}, "!" ); ,则只需在int128_t intType_t定义中添加它即可。

请注意:没有保证满足前面的using

首先,因为标准保证一个字节至少为8位;但可以超过8位。如果一个字节是16位,则来自

static_assert()

您会得到 32 位的类型。

第二,因为using t16 = intType_t<2u>; 类型是可选的。