将 std::array 与初始化列表一起使用

发布于 2024-12-16 14:59:21 字数 391 浏览 2 评论 0原文

除非我弄错了,否则应该可以通过以下方式创建 std:array:

std::array<std::string, 2> strings = { "a", "b" };
std::array<std::string, 2> strings({ "a", "b" });

然而,使用 GCC 4.6.1 我无法让其中任何一个工作。编译器只是说:

expected primary-expression before ',' token

但初始化列表与 std::vector 一起工作得很好。那么是哪一个呢?我是否错误地认为 std::array 应该接受初始化列表,或者 GNU 标准 C++ 库团队犯了错误?

Unless I am mistaken, it should be possible to create a std:array in these ways:

std::array<std::string, 2> strings = { "a", "b" };
std::array<std::string, 2> strings({ "a", "b" });

And yet, using GCC 4.6.1 I am unable to get any of these to work. The compiler simply says:

expected primary-expression before ',' token

and yet initialization lists work just fine with std::vector. So which is it? Am I mistaken to think std::array should accept initialization lists, or has the GNU Standard C++ Library team goofed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤独岁月 2024-12-23 14:59:21

std::array 很有趣。它的定义基本上是这样的:

template<typename T, int size>
struct std::array
{
  T a[size];
};

它是一个包含数组的结构。它没有采用初始值设定项列表的构造函数。但 std::array 是 C++11 规则下的聚合,因此可以通过聚合初始化来创建。要聚合初始化结构体内部的数组,您需要第二组大括号:

std::array<std::string, 2> strings = {{ "a", "b" }};

请注意,标准确实建议在这种情况下可以省略额外的大括号。所以这很可能是一个 GCC 错误。

std::array is funny. It is defined basically like this:

template<typename T, int size>
struct std::array
{
  T a[size];
};

It is a struct which contains an array. It does not have a constructor that takes an initializer list. But std::array is an aggregate by the rules of C++11, and therefore it can be created by aggregate initialization. To aggregate initialize the array inside the struct, you need a second set of curly braces:

std::array<std::string, 2> strings = {{ "a", "b" }};

Note that the standard does suggest that the extra braces can be elided in this case. So it likely is a GCC bug.

不知在何时 2024-12-23 14:59:21

添加到已接受的答案:

std::array<char, 2> a1{'a', 'b'};
std::array<char, 2> a2 = {'a', 'b'};
std::array<char, 2> a3{{'a', 'b'}};
std::array<char, 2> a4 = {{'a', 'b'}};

所有工作都在 GCC 4.6.3 (Xubuntu 12.01) 上进行。但是,

void f(std::array<char, 2> a)
{
}

//f({'a', 'b'}); //doesn't compile
f({{'a', 'b'}});

上面的代码需要双括号才能编译。带单括号的版本会导致以下错误:

../src/main.cc: In function ‘int main(int, char**)’:
../src/main.cc:23:17: error: could not convert ‘{'a', 'b'}’ from ‘<brace-enclosed initializer list>’ to ‘std::array<char, 2ul>’

我不确定类型推断/转换的哪个方面使事情以这种方式工作,或者这是否是 GCC 实现的一个怪癖。

To add to the accepted answer:

std::array<char, 2> a1{'a', 'b'};
std::array<char, 2> a2 = {'a', 'b'};
std::array<char, 2> a3{{'a', 'b'}};
std::array<char, 2> a4 = {{'a', 'b'}};

all work on GCC 4.6.3 (Xubuntu 12.01). However,

void f(std::array<char, 2> a)
{
}

//f({'a', 'b'}); //doesn't compile
f({{'a', 'b'}});

the above requires double braces to compile. The version with single braces results in the following error:

../src/main.cc: In function ‘int main(int, char**)’:
../src/main.cc:23:17: error: could not convert ‘{'a', 'b'}’ from ‘<brace-enclosed initializer list>’ to ‘std::array<char, 2ul>’

I'm not sure what aspect of type inference/conversion makes things work this way, or if this is a quirk of GCC's implementation.

尸血腥色 2024-12-23 14:59:21

有点晚了,但这就是我在 C++17 中的做法。
不使用初始值设定项列表,仅使用可变值列表。
像这样: auto ar2 = create_array(1, 2, 3, 4);

#include <array>
#include <type_traits>

namespace traits
{

template<typename T, typename... Ts>
struct array_type
{
  using type = T;
};

template<typename T, typename... Ts>
static constexpr bool are_same_type()
{
  return std::conjunction_v<std::is_same<T, Ts>...>;
}

}

template<typename... T>
constexpr auto create_array(const T&&... values)
{
  using array_type = typename traits::array_type<T...>::type;
  static_assert(sizeof...(T) > 0, "an array must have at least one element");
  static_assert(traits::are_same_type<T...>(), "all elements must have same type");
  return std::array<array_type, sizeof...(T)>{ values... };
}

template<typename T, typename... Ts>
constexpr auto create_array_t(const Ts&&... values)
{
  using array_type = T;
  static_assert(sizeof...(Ts) > 0, "an array must have at least one element");
  static_assert(traits::are_same_type<Ts...>(), "all elements must have same type");
  return std::array<array_type, sizeof...(Ts)>{ static_cast<T>(values)... };
}

// to create a std::array of specific type
auto ar = create_array_t<std::uint8_t>(1u, 2u, 3u, 4u);
static_assert(ar.size() == 4);

// to create an array and let the compiler deduce its type
auto ar2 = create_array(1, 2, 3, 4);
static_assert(ar2.size() == 4);

A bit late to the game but this is how I do it in C++17.
Not using an initializer list just a variadic list of values.
like this : auto ar2 = create_array(1, 2, 3, 4);

#include <array>
#include <type_traits>

namespace traits
{

template<typename T, typename... Ts>
struct array_type
{
  using type = T;
};

template<typename T, typename... Ts>
static constexpr bool are_same_type()
{
  return std::conjunction_v<std::is_same<T, Ts>...>;
}

}

template<typename... T>
constexpr auto create_array(const T&&... values)
{
  using array_type = typename traits::array_type<T...>::type;
  static_assert(sizeof...(T) > 0, "an array must have at least one element");
  static_assert(traits::are_same_type<T...>(), "all elements must have same type");
  return std::array<array_type, sizeof...(T)>{ values... };
}

template<typename T, typename... Ts>
constexpr auto create_array_t(const Ts&&... values)
{
  using array_type = T;
  static_assert(sizeof...(Ts) > 0, "an array must have at least one element");
  static_assert(traits::are_same_type<Ts...>(), "all elements must have same type");
  return std::array<array_type, sizeof...(Ts)>{ static_cast<T>(values)... };
}

// to create a std::array of specific type
auto ar = create_array_t<std::uint8_t>(1u, 2u, 3u, 4u);
static_assert(ar.size() == 4);

// to create an array and let the compiler deduce its type
auto ar2 = create_array(1, 2, 3, 4);
static_assert(ar2.size() == 4);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文