【问题标题】:Getting the number of elements in std::array at compile time在编译时获取 std::array 中的元素数
【发布时间】:2013-06-01 06:26:17
【问题描述】:

以下是有效的 C++ 代码吗?为什么不是?

std::array<std::string, 42> a1;
std::array<int, a1.size()> a2;

它不能在 GCC 4.8(在 C++11 模式下)编译。有一个简单但不优雅的解决方法:

std::array<std::string, 42> a1;
std::array<int, sizeof(a1)/sizeof(a1[0])> a2;

很明显,编译器可以计算出 std::array 中元素的数量。为什么 std::array::size() 不是constexpr static 函数?

编辑: 我找到了另一种解决方法:

std::array<std::string, 42> a1;
std::array<int, std::tuple_size<decltype(a1)>::value> a2;

【问题讨论】:

  • 你在使用-std=c++0x标志吗?
  • 对了,是clearly constexpr()
  • 与其给a1一个大小,然后给a2同样大小,为什么不直接创建一个像size_t x=42这样的变量,然后同时创建一个大小的a1a2x?
  • @Lorkenpeist:因为也许你有auto a1 = some_function&lt;some_template_argument&gt;();
  • 元组大小的解决方案非常好。专门为此目的为 std::array 重载了该函数(请参阅here

标签: c++


【解决方案1】:

array&lt;T&gt;::size()constexpr,但您不能以这种方式使用它,因为 a1 不是 constexpr 值。此外,它不能是 constexpr,因为 string 不是文字类型。

但是,如果需要,您可以通过推导 size_t 模板参数来解决此问题。示例:

#include <string>
#include <array>
#include <iostream>
using namespace std;

template<typename>
struct array_size;
template<typename T, size_t N>
struct array_size<array<T,N> > {
    static size_t const size = N;
};

array<string, 42> a1;
array<string, array_size<decltype(a1)>::size> a2;

int main() {
    cout << a2.size() << endl;
}

【讨论】:

  • 这就是为什么size() 应该是static 函数,正如问题中所建议的那样。
  • @BenVoigt 如果 size 是一个静态的 constexpr 函数,会不会有问题?
  • @robson: 是的,因为那将是constexpr,仅取决于是否所有参数都是constexpr(由于参数为零,因此很容易满足),而不取决于对象实例是否@987654334 @ 是constexpr
  • 其实标准库中已经有array_size这样的推导模板:std::tuple_size&lt;some_array_type&gt;::value (C++11)。在 C++17 中,您还可以找到常用的便利助手 std::tuple_size_v&lt;some_array_type&gt;
  • @bumpanck 您应该将此作为答案发布,这应该是公认的答案!
【解决方案2】:

根据 C++11 标准的第 23.3.2.1 节,std::array::size 实际上需要为 constexpr

23.3.2.4 array::size [array.size]  
template <class T, size_t N> constexpr size_type array<T,N>::size() noexcept;  
Returns: N

我猜这只是滑过了在 GCC 中实现它的人。


经过测试,这是可行的:

std::array<int, 42> a1;
std::array<int, a1.size()> a2;

这实际上可能与 std::string 不是生成编译时实例的有效 constexpr 类型有关,而 int 是。

【讨论】:

    【解决方案3】:

    您可以使用与 C++98 数组边界检测相同的模板推断方法。

    template<size_t N, typename T>
    constant_integer<N> array_size( const std::array<T, N>& );
    

    制作一个漂亮的宏包装器,尽情享受吧!

    许多变体也是可能的,例如:

    【讨论】:

    • 返回什么?这不是一个有效的 c++
    • @BЈовић:当constant_integer&lt;N&gt; 有一个默认构造函数时。点击查看完整的源代码。
    • 应该return constant_integer&lt;N&gt;();。不仅仅是return;
    • @BЈовић:实际上,函数体甚至都不需要。
    • @BЈовић,请记住,从未评估过任何函数调用。
    【解决方案4】:

    它不是静态的,而是constexpr http://www.cplusplus.com/reference/array/array/size/
    编辑:这可能不是一个错误,看看这个Error using a constexpr as a template parameter within the same class

    【讨论】:

      猜你喜欢
      • 2022-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多