首页 > 解决方案 > 具有动态选择的 C++ 模板类型

问题描述

我正在寻找一种允许编译器为模板参数中的给定整数选择最小数据类型的构造。我自己找不到解决方案的问题是我想如何使用它:

template<typename T, min_type<max_elements_to_store> max_elements_to_store>
class testClass {
private:
    T data[max_elements_to_store];
    min_type<max_elements_to_store> currently_selected_element;
};

宏“min_type”应该为给定的 max_elements_to_store (uint8_t, uint16_t, uint32_t, uint64_t) 动态选择具有最小位数的类型。我可以通过简单地将 min_type<> 替换为给定的数据类型来修复它,但这种数据类型通常不是最好的选择。例如,

template<typename T, uint64_t max_elements_to_store>
class testClass {
private:
    T data[max_elements_to_store];
    uint64_t currently_selected_element;
};

TestClass<uint8_t, 12> testObject;

在这里,数组只能保存 12 个元素,而 current_selected_element 变量浪费了很多位,而这些位对于仅访问 12 个元素来说是不必要的。这似乎只是一个小问题,但对于访问类中数据的许多变量来说,情况会变得更糟......

这个问题有解决方案吗?我希望很清楚我在寻找什么。

提前致谢!启发

标签: c++templates

解决方案


一种方法是使用std::conditional

#include <type_traits>
#include <cstdint>
#include <limits>

template<std::size_t Count>
using min_type = std::conditional_t<Count <= std::numeric_limits<uint8_t>::max(), uint8_t,
                    std::conditional_t<Count <= std::numeric_limits<uint16_t>::max(), uint16_t,
                        std::conditional_t<Count <= std::numeric_limits<uint32_t>::max(), uint32_t,
                            std::conditional_t<Count <= std::numeric_limits<uint64_t>::max(), uint64_t, void>>>>;

// test: all of the following pass            
static_assert(std::is_same_v<min_type<12>, uint8_t>);
static_assert(std::is_same_v<min_type<1024>, uint16_t>);
static_assert(std::is_same_v<min_type<70000>, uint32_t>);
static_assert(std::is_same_v<min_type<5000000000>, uint64_t>);

template<typename T, std::size_t max_elements_to_store>
class testClass {
private:
    T data[max_elements_to_store];
    min_type<max_elements_to_store> currently_selected_element;
};

TestClass<uint8_t, 12> testObject;

注意:正如@François Andrieux 在评论中指出的那样,由于填充,这不会节省任何内存(除非您使用编译器特定的扩展来强制类的打包表示)。


推荐阅读