55

私が間違っていない限り、次の方法で 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++ ライブラリ チームは間抜けですか?

4

3 に答える 3

93

std::arrayは面白い。基本的には次のように定義されます。

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

配列を含む構造体です。初期化子リストを取るコンストラクターはありません。ただしstd::array、C++11 の規則では集合体であるため、集合体の初期化によって作成できます。構造体内の配列を集約して初期化するには、中かっこの 2 番目のセットが必要です。

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

この場合、余分なブレースを省略できることを標準が示唆していることに注意してください。したがって、GCC のバグである可能性があります。

于 2011-11-19T06:09:41.837 に答える
12

受け入れられた回答に追加するには:

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'}});

上記をコンパイルするには二重中括弧が必要です。中括弧が 1 つのバージョンでは、次のエラーが発生します。

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

型推論/変換のどの側面がこのように機能するのか、またはこれが GCC の実装の癖なのかはわかりません。

于 2012-09-27T08:11:30.473 に答える
2

ゲームには少し遅れていますが、これは 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);
于 2021-08-12T11:15:14.587 に答える