2017-02-12 4 views
4

コンパイル時に既知のインデックスと実行時に静的にアサートする方法はありますか?例:インデックス上のstatic_assertはコンパイル時に知ります

template <class T, int Dim> 
class Foo 
{ 
    T _data[Dim]; 
    public: 
     const T &operator[](int idx) const 
     { 
      static_assert(idx < Dim, "out of range"); // error C2131: expression did not evaluate to a constant 
      return _data[idx]; 
     } 
}; 

int main() 
{ 
    Foo<float, 2> foo; 

    foo[0]; 
    foo[1]; 
    foo[2]; // compiler error 

    for (int i=0; i<5; ++i) 
    { 
     foo[i]; // run time assert when i > 1 
    } 

    return 0; 
} 
+0

ありがとうございました。 – sharvey

+0

GCCについては__builtin_constant_pを見ることができますが、あなたが提案していることをしようとすると、GCCで本当に奇妙な振る舞いがあるので、完璧な解決策は得られません。 –

+0

あなたの 'foo [2]'アクセスは 'constexpr'コンテキストでは実行されず、あなたの演算子も' constexpr'ではありません。コンパイル時エラーは発生しません。あなたの目標を達成するには、 'assert'を使います(' static_assert'ではなく 'non-'constexpr'呼び出しエラーを返します)。 –

答えて

1

1つの機能で何が欲しいかを知ることはできません。

constexpr関数を開発したとしても、実行時と実行時のコンパイル時間を検出できず、別の方法で動作するとは思われません。

しかし、さまざまな機能を開発することができます。例によって

、テンプレート引数のみで計算指標を受信することができる指標コンパイル時に知られており、それはstatic_assert()を実行することができ、そしてat(std::size_t)、一緒に使用することができる指標であるテンプレートget<>()、ランタイムチェックでランタイム。

エンアンパッサン:

1)私はSTLでいつものように、提案し、バインドのためのat()の使用は

2バインド未チェックのアクセスのためのアクセスとoperator[]()をチェックする)と私はの使用を示唆符号なしインデックスか、インデックスが>= 0であることを確認する必要があります。

次はあなたが単に例外を投げるか、主張することができ作業例

#include <iostream> 
#include <stdexcept> 

template <class T, std::size_t Dim> 
class Foo 
{ 
    private: 
     T _data[Dim]; 

    public: 
     T const & operator[] (std::size_t idx) const 
     { return _data[idx]; } 

     template <std::size_t IDX> 
     T const & get() const 
     { 
     static_assert(IDX < Dim, "out of range"); 

     return this->operator[](IDX); 
     } 

     T const & at (std::size_t idx) const 
     { 
     if (idx >= Dim) 
      throw std::range_error("out of range"); 

     return this->operator[](idx); 
     } 
}; 

int main() 
{ 
    Foo<float, 2U> foo; 

    foo.get<0U>(); 
    foo.get<1U>(); 
    //foo.get<2U>(); // compiler error 

    for (auto i = 0U ; i < 5U ; ++i) 
     foo.at(i); // run time exception when i > 1 

    return 0; 
} 
+0

その答えをありがとうございます、それはうまく動作します。興味深いことに、インデックスパラメータがコンパイル時に知られているかどうかに応じて、 'get'と' at'の両方の振る舞いを持つ関数を書くことは可能でしょうか? – sharvey

+0

@sharvey - 私はそれが可能だとは思わない。もしあなたがそれができると分かったら、私に方法を教えてください。 – max66

3

です。 constexprコンテキストでコンパイルに失敗します。これは、スローする条件がconstexprコンテキストで評価できる場合にのみ機能します。 gccのバージョンによっては、スローが動作しないようにするバグがあることに注意してください。

関連する問題