2011-12-08 24 views
0

私はいくつかの奇妙な動作に遭遇しました。これがうまくいくかどうかわからない。私はそれを機能させるつもりではないことに注意してください、私はむしろ理論的側面に関心を持っています。私は明らかにテンプレートクラスSequenceCheckResultがdirectiontypeという名前の列挙型を含むVisual C++ 2010を使用して、次のコードにC++テンプレートとオーバーロード演算子

template <class T_> 
ostream &operator <<(std::ostream &out, 
     typename SequenceCheckResult<T_>::directiontype const &direction) { 

    switch(direction) { 
    case SequenceCheckResult<T_>::None: 
     out<<"none o"; 
     break; 
    case SequenceCheckResult<T_>::Horizontal: 
     out<<"horizontal _"; 
     break; 
    case SequenceCheckResult<T_>::Vertical: 
     out<<"vertical |"; 
     break; 
    case SequenceCheckResult<T_>::ForwardDiagonal: 
     out<<"forward diagonal \\"; 
     break; 
    case SequenceCheckResult<T_>::BackwardDiagonal: 
     out<<"backward diagonal /"; 
     break; 
    } 

    return out; 
} 

を守っています。上記のコードはインスタンス化されず、変数の整数値が出力されます。私が専門性を提供しても、それはまだ機能しません。次の関数を作成すると、その関数が使用され、テキスト値が出力されます。上記の関数の次のコードとintの特殊化は、template<>行と<int>の次のコードがoperator <<と異なることに注意してください。

ostream &operator << (std::ostream &out, 
     SequenceCheckResult<int>::directiontype const &direction) { 

    switch(direction) { 
    case SequenceCheckResult<int>::None: 
     out<<"none o"; 
     break; 
    case SequenceCheckResult<int>::Horizontal: 
     out<<"horizontal _"; 
     break; 
    case SequenceCheckResult<int>::Vertical: 
     out<<"vertical |"; 
     break; 
    case SequenceCheckResult<int>::ForwardDiagonal: 
     out<<"forward diagonal \\"; 
     break; 
    case SequenceCheckResult<int>::BackwardDiagonal: 
     out<<"backward diagonal /"; 
     break; 
    } 

    return out; 
} 

私は考えられる原因があり、これがなぜ起こるか知りたい:

  • コンパイラのバグ
  • 実装は、この動作
  • 基準は、私が何か
  • をしないのです。この動作
  • を定義定義

ありがとうございましたvance

+0

もっとコードしてください。これをどのように呼んでいるのか教えてください。 – jmucchiello

+0

@jmucchiello:std :: cout << obj.direction; –

答えて

6

あなたのアプローチは動作しません。 「要素に基づいたコンテナ」を推論することはできません!簡単な引数に

、この思考実験考える:今、私はdeduce_me(5)を呼び出す場合

struct Foo { typedef int type; } 
struct Bar { typedef int type; } 

template <typename T> void deduce_me(typename T::type n) { } 

は、どのように我々はFooまたはBarのいずれかを推定することになっていますか? SequenceCheckResult<_T>の与えられた専門のため、​​は、まだ我々は、少なくともやったにも関わらず、あらゆるタイプの可能性があるため(

+0

定数を入力すると明らかになりました。元の呼び出しはcout << obj.directionでした –

1

SequenceCheckResult<int>::directiontypeは、(それが正確だから)intよりSequenceCheckResult<int>::directiontypeのためのより良い一致があるが、intSequenceCheckResult<_T>::directiontypeよりも一致ですタイプがtypenameであることを指定します)。

編集:KerrekSBが指摘するようにと、たとえ​​が何とか使用する_T決定する方法で私たちを残している、すべての_Tためintあることが知られていた、それは我々がそれはdoesnの知っているにもかかわらず、問題が発生します実際には_Tが使用されます。

これを回避するには、テンプレートクラスの外で列挙型を定義します。それを内部で定義すると、_Tに依存していますが、実際にはそうではありません。スコープには便利だと思われるかもしれませんが、これを書いているのはoperator<<なので、とにかくアクセスを完全に制限することはできません。さらに、コンストラクタやファクトリメソッドは実際に​​への外部アクセスの恩恵を受ける可能性があります。

関連する問題