【问题标题】:Get size of std::array without an instance在没有实例的情况下获取 std::array 的大小
【发布时间】:2016-12-29 02:39:34
【问题描述】:

鉴于此结构:

struct Foo {
  std::array<int, 8> bar;
};

如果我没有Foo 的实例,如何获取bar 数组的元素数?

【问题讨论】:

  • 使用宏而不是硬编码数组大小怎么样?
  • @WebertS.Lima - 放弃这个想法。不是宏。
  • @WebertS.Lima - std::array 不会缩小或增长。它将始终是 8 个构造对象。
  • @WebertS.Lima - 不;如果您声明std::array&lt;int, 8&gt;,您将拥有一个包含 8 个元素的容器;您可以设置其中 4 个元素的值(在初始化之后),但其他 4 个元素存在初始值
  • 另外,数组还不存在,我当然希望它不是半满的。

标签: c++ c++11 stdarray


【解决方案1】:

您可以使用std::tuple_size:

std::tuple_size<decltype(Foo::bar)>::value

【讨论】:

  • 在这里挂钩:处理std::tuples(std::tuple_sizestd::tuple_elementstd::get)的各种类和函数都有方便的专门化处理std::array&lt;T, N&gt; 就像std::tuple&lt;T, T, ..., T&gt; .
【解决方案2】:

尽管有@Jarod42 的good answer,这里还有一个基于decltype 的可能解决方案,它不使用tuple_size
它遵循一个适用于 C++11 的最小工作示例:

#include<array>

struct Foo {
    std::array<int, 8> bar;
};

int main() {
    constexpr std::size_t N = decltype(Foo::bar){}.size();
    static_assert(N == 8, "!");
}

std::array 已经有一个名为 size 的 constexpr 成员函数,它返回您要查找的值。

【讨论】:

  • 所以这与下面@waxrat 的答案有相同的问题,即使该构造可能constexpr,它也需要构造,从这个意义上说std::tuple_size 是一个更好的答案因为它在非constexpr 的情况下不需要任何构造或破坏。
  • @Mgetz 我没有说它更好。 :-) ...不同的解决方案和答案可以帮助未来的读者,无论他们是否被接受。
  • 因此我的评论,我试图确保这些读者能够理解为什么std::tuple_size 是一个更好的选择。也就是说,为了便于阅读,我可能会做一个using array_size = std::tuple_size
  • @Mgetz 名称不是该语言最强大的功能,我同意。我们正在处理一种语言,它包含一个名为std::move 的函数,它不会移动任何东西。还有什么? :-)(注意:只是开玩笑)
  • 此答案与另一个答案具有相同的problem(“对于没有默认构造函数的类将不起作用”)此外,(对于非平凡类型)它将执行构造函数 N 次(可能有副作用)。
【解决方案3】:

你可以给Foo一个public static constexpr成员。

struct Foo {
 static constexpr std::size_t bar_size = 8;
 std::array<int, bar_size> bar;
}

现在您从 Foo::bar_size 知道了 bar 的大小,并且如果 Foo 曾经有多个相同大小的数组,您可以更灵活地将 bar_size 命名为更具描述性的名称。

【讨论】:

  • 鉴于其他答案表明没有static const 也可以做到这一点,我认为这不是一个好的答案。
  • @Tas:在我看来,问题在于这个答案让事情倒退了:它没有回答如何获取一些现有数组的元素数量的问题,而是说声明一个已知数字并改变数组的声明以对其进行模板化。所以,static constexpr 会员真的不是什么可抱怨的;它不会在实例中消耗任何空间,并在其翻译单元中被完全优化(除非它的地址被占用,但这需要一个外线定义,所以)。
  • @Tas @underscore_d 谢谢。我做出这个答案的原因是因为高分答案很复杂。没有static constexpr 的条形大小是一个神奇的数字。这个解决方案去掉了幻数,用一条简单的线解决了问题。
【解决方案4】:

您可以像处理旧数组一样执行此操作:

sizeof(Foo::bar) / sizeof(Foo::bar[0])

【讨论】:

  • 或使用更易读的std::extent 但这不是答案,因为这仍然需要构造一个实例。
  • 其他一些需要记住的事情 sizeof std::array&lt;int, 4&gt; 可能不等于 sizeof int[4] 这是一个实现细节。此外,如果您要构建std::array,那么只需使用size() 成员
  • 我的意思是sizeof(Foo::bar) / sizeof(Foo::bar[0])。不需要 Foo 的实例。
  • @Mgetz 难道std::array 的其他明显要求意味着它必须具有与现实中的原始数组相同的大小和布局,即使没有明确要求?
  • @underscore_d 实际上是的,但它仍然依赖于实现。因此我不相信它,编译器可以做太多事情来搞砸这个,std::array 有一个 size() 成员。
【解决方案5】:

用途:

sizeof(Foo::bar) / sizeof(int)

【讨论】:

  • 我试过了,我得到了相同的价值。 #include &lt;iostream&gt; #include &lt;array&gt; using namespace std; struct Foo { std::array&lt;int, 8&gt; bar; }; int main() { cout &lt;&lt; sizeof(Foo::bar) / sizeof(int) &lt;&lt; endl; cout &lt;&lt; std::tuple_size&lt;decltype(Foo::bar)&gt;::value &lt;&lt; endl; return 0; }
【解决方案6】:

你可以像这样使用:

sizeof Foo().bar

【讨论】:

  • this comment from OP:他关注的是元素的数量,而不是总大小。
  • @Happy - OP修改了答案:他想要数组中的元素数(示例中为8),而不是sizeof
  • 注意:对于没有默认构造函数的类将不起作用
  • @M.M 因为sizeof 不计算它的操作数,你总是可以只使用std::declval&lt;Foo&gt;()
  • @Angew 技术上 std::array 被允许有填充
猜你喜欢
  • 1970-01-01
  • 2011-10-18
  • 2011-01-14
  • 2020-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多