36

libstdc++ (v. 4.6) でa として宣言されているのにstd::initializer_list<_E>::size、 a で許可されないのはなぜですか?static_assertconstexpr

たとえば、次のコード:

template<class T, int Length>
class Point
{
  public:
    Point(std::initializer_list<T> init)
    {
      static_assert(init.size() == Length, "Wrong number of dimensions");
    }
};

int main()
{
  Point<int, 3> q({1,2,3});

  return 0;
}

次のエラーが発生します。

test.C: In constructor ‘Point<T, Length>::Point(std::initializer_list<_Tp>) [with T = int, int Length = 3]’:
test.C:60:26:   instantiated from here
test.C:54:7: error: non-constant condition for static assertion
test.C:54:73:   in constexpr expansion of ‘init.std::initializer_list<_E>::size [with _E = int, std::initializer_list<_E>::size_type = long unsigned int]()’
test.C:54:7: error: ‘init’ is not a constant expression

これは、簡単な例では問題なく機能することに注意してください。

class A
{
  public:
    constexpr int size() { return 5; }
};

int main()
{
  A a;
  static_assert(a.size() == 4, "oh no!");

  return 0;
}
4

5 に答える 5

34

「イニシャライザリスト」はただのひどいクラッジです。

してはいけないこと:

#include <initializer_list>

template<typename T>
void Dont(std::initializer_list<T> list) { // Bad!
    static_assert(list.size() == 3, "Exactly three elements are required.");
}

void Test() { Dont({1,2,3}); }

行う:

template<typename T, std::size_t N>
void Do(const T(&list)[N]) { // Good!
    static_assert(N == 3, "Exactly three elements are required.");
}

void Test() { Do({1,2,3}); }
于 2016-07-31T01:12:39.157 に答える
11

コンパイラは、init.size() ではなく、init が問題であると言います。

コンストラクターは、さまざまな長さの初期化子を使用してさまざまな場所から呼び出すことができると思います。

(詳しく説明すると、 variable の実行時の値、つまり変数の要素数static_assertに依存するa を記述しようとしています。s は、関数がコンパイルされた時点で評価可能でなければなりません。あなたのコードは、これに簡単に類似しています無効な例:)initstatic_assert

void foo(int i) { static_assert(i == 42, ""); }
int main() { foo(42); }  // but what if there's a caller in another translation unit?
于 2011-03-25T22:31:38.377 に答える
5

@Evgeny との議論から、これは ( でgcc 4.8 c++11) うまく機能し、イニシャライザ リスト (で) で互換性のあるサイズのみを受け入れることでサイズ チェックを行うことができることに気付きましたmain

(コードリンク: http://coliru.stacked-crooked.com/a/746e0ae99c518cd6 )

#include<array>
template<class T, int Length>
class Point
{
  public:
    Point(std::array<T, Length> init)
    {
//not needed//      static_assert(init.size() == Length, "Wrong number of dimensions");
    }
};

int main()
{
  Point<int, 3> q({1,2,3}); //ok
//  Point<int, 3> q2({1,2,3,4}); //compile error (good!)
  Point<int, 3> q2({1,2}); // ok, compiles, same as {1,2,0}, feature or bug?
  return 0;
}
于 2013-11-12T11:12:45.103 に答える