获取C++模板参数包的总大小(以字节为单位)

Getting total size in bytes of C++ template parameter pack

本文关键字:字节 为单位 C++ 参数 获取      更新时间:2023-10-16

我正在尝试创建一个以字节为单位返回参数包总大小的函数,并且找不到解决方案!

template <typename... TTypes>
struct Test {
  constexpr size_t getPackSizeInBytes() const {
   // sizeof(TTypes) gives `unexpanded pack` error
  }
};
// What I'm hoping for:
Test<uint8, uint16> test;
std::cout << test.getPackSizeInBytes() << std::endl;
// Should output 3;

感谢您的帮助!

您可以在 C++17 中使用一元折叠:

return (sizeof(TTypes) + ... + 0);

如果你没有C++17,那么你必须用更手动的方式解压缩它,尽管更丑陋:

int sum = 0;
using I = std::size_t[];
(void)(I{0u, sum += sizeof(TTypes)...});
return sum;

这是否符合您的要求:

// Pre C++17 code (not sure but I belive it is easier in C++17)
#include <iostream>
#include <numeric>
template<typename... TTypes>
struct Test
{
    constexpr size_t getPackSizeInBytes() const
    {
        size_t data[] = {sizeof(TTypes)...};
        return std::accumulate(std::begin(data), std::end(data), 0);
    }
};
int main() 
{
    Test<std::uint8_t, std::uint16_t> test;
    std::cout << test.getPackSizeInBytes() << "n";
}

基于这个答案的替代(可移植但递归(解决方案,甚至不是"Pre C++17",甚至可能是"Pre C++11":)(甚至可以在Arduino中工作,没有任何依赖关系(

template <typename ... Args> 
struct count_bytes;
template <>
struct count_bytes<> {
    constexpr static size_t value = 0u;
};
template <typename T, typename... Args>
struct count_bytes<T, Args...> {
    constexpr static size_t value = sizeof(T) + count_bytes<Args...>::value;
};
// ----------------------------------------------------------------
// Compile-time testing
static_assert(count_bytes<int8_t, int16_t>::value             ==  3, "Test failed");
static_assert(count_bytes<int8_t, int16_t, int32_t>::value    ==  7, "Test failed");
static_assert(count_bytes<float, float, float, double>::value == 20, "Test failed");
// Test for known-size fixed array
static_assert(count_bytes<int, int[2]>::value                 == 12, "Test failed");
// Attention: sizeof(void) works for C, but not for C++. Reference: https://stackoverflow.com/a/1666232/
// static_assert(count_bytes<void>::value                     ==  1, "Test failed");