【问题标题】:Getting total size in bytes of C++ template parameter pack获取 C++ 模板参数包的总大小(以字节为单位)
【发布时间】:2019-07-29 02:34:47
【问题描述】:

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

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;

感谢您的帮助!

【问题讨论】:

  • @songyuanyao 你为什么删除你的答案?
  • @MartinYork 我认为 OP 想在每种类型上调用 sizeof 并获取摘要。
  • 当您说// Should output 3; 时,您的意思是应该是sizeof(uint8) + sizeof(uint16)。我不想假设非标准类型的大小。虽然 std::uint8_tstd::uint16_t 应该是 24 位。但这并不意味着一个字节是 8 位。你需要检查CHAR_BITS
  • 请注意,计算类型的各个大小的总和通常不会产生与将相同类型封装为成员的结构相同的值。对齐要求通常意味着这样的结构比其单个组件更大。

标签: c++ templates


【解决方案1】:

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

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

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

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

【讨论】:

  • 为什么不是二进制折叠 (sizeof(TTypes) + ... + 0) ?如果参数包为空怎么办?
【解决方案2】:

这是否符合您的要求:

// 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";
}

【讨论】:

  • 是的!谢谢您的答复!您介意告诉我{sizeof(TTypes)...} 语法是什么,以便我查找吗?
  • @Dukuna_Matata the elipses ... 仅仅意味着扩展刚刚使用的参数包。因此,sizeof(TTypes) 部分会针对每个模板参数展开一次(逗号分隔)。
【解决方案3】:

基于this answer 的替代(可移植但递归)解决方案,甚至不是“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");

【讨论】:

    猜你喜欢
    • 2016-04-08
    • 1970-01-01
    • 2010-09-17
    • 1970-01-01
    • 2013-02-01
    • 2021-08-31
    • 2018-01-01
    • 2013-02-06
    相关资源
    最近更新 更多