2016-10-18 4 views
1

私はこれらのコード行に出くわした:負の配列インデックスと一見冗長なテンプレートの使用

template< int I > struct arg 
{ 
    arg() 
    { 
    } 

    template< class T > arg(T const & /* t */) 
    { 
     // static assert I == is_placeholder<T>::value 
     typedef char T_must_be_placeholder[ I == is_placeholder<T>::value? 1: -1 ]; 
    } 
}; 

template< class T > struct is_placeholder 
{ 
    enum _vt { value = 0 }; 
}; 

型名Tはどこにも内部に使用されていない間、構造体is_placeholderがテンプレート化された理由は何ができますか?

なぜT_must_be_placeholderが無効なサイズ-1を持つように定義されているのですか?これを実現するために、私はarg<1>(1)と呼ばれ、error: size of array is negativeを期待通りに与えました。それはある種のサニティチェックテクニックですか? arg<1>(1)呼び出しが行われないと、コンパイラはこの問題を報告しないのはなぜですか?

int i = 0; 
char a[i == 1 ? 1 : -1]; //No error 

健全性チェックは、第一例のために働く場合

が、その後、どのようにそれは、第1のために失敗するのですか?

+0

これは、static_assertの貧弱な実装です。条件が満たされない場合、負のサイズの配列が宣言され、コンパイルエラーが発生します。 –

+0

最後の例は、配列のサイズが定数式ではないため、コンパイルしないでください。おそらく、GCCの拡張機能のために、負のサイズを渡すとどうなるかわからないでしょう。 – sbabbi

+0

驚いたことに、これはhttp://ideone.com/LrWvHhをコンパイルします。チェックアウト。 –

答えて

0

is_placeholderは、異なるTに特化できるようにテンプレートです。私はこれだろう、私は構造体exampleを作成し、is_placeholder<example>::valueは42になりたいと言う:(私達はちょうど42であることを専門とする)is_placeholder<example>::valueこの場合T_must_be_placeholderチェックを

struct example {}; 

template< class T > struct is_placeholder 
{ 
    enum _vt { value = 0 }; 
}; 

template<> 
struct is_placeholder<example> 
{ 
    enum _vt { value = 42 }; 
}; 

template< int I > struct arg 
{ 
    arg() 
    { 
    } 

    template< class T > arg(T const & /* t */) 
    { 
     // static assert I == is_placeholder<T>::value 
     typedef char T_must_be_placeholder[ I == is_placeholder<T>::value ? 1: -1 ]; 
    } 
}; 

void test() 
{ 
    auto x = arg<42>(example()); // compiles 
    auto y = arg<43>(example()); // assertion 
    return 0; 
} 

Iと同じです。したがって、Iが42の場合、それはコンパイルされますが、Iが他のものであれば、それはありません。

負のサイズの配列を作成しようとすると、意図的にコードがコンパイルされるのを防ぐことができます。したがって、これはおそらくサニティチェック(コメント内の静的アサーション)です。

+0

なぜ 'is_placeholder'がテンプレート化されているのですか?申し訳ありませんが、私はテンプレートを使用するのに慣れていません。 :| –

+0

なぜ、 'int i = 0; char a [i == 1? 1:-1]; 'それから失敗しますか? –

+0

@SauravSahu VLA(実行時に既知のサイズの配列の拡張子gcc)があるためです。コンパイルエラーではなく実行時に可変サイズの配列がスタックに割り当てられることが静的に認識されていないため、私は疑問を感じます。 – bolov

関連する問題