2016-10-20 4 views
0

Visual Studio 2015 Community EditionでMSVCの最新バージョンを使用しています。テンプレートの特殊化と演算子のオーバーロードに関する問題があります。特殊なテンプレートを使用した場合のオペレータエラーの未定義

私は次の(ヘッダーのみ)ベクトルクラススニペットを持っています。不要なコードを除外しました(vec2とvec4の同一の特殊化)。以下特化した

template <typename T, int n> 
struct VectorN 
{ 
    T data[n]; 

    T& operator[](const int i); 
}; 

template <typename T, int n> 
T& VectorN<T, n>::operator[](const int i) 
{ 
    static_assert(i >= 0 && i < n, "Index out of range"); 
    return data[i]; 
} 

template <typename T, int n> 
std::ostream& operator<<(std::ostream& os, const VectorN<T, n>& vec) 
{ 
    for (auto i = 0; i < n; ++i) 
    { 
     os << vec[i]; 
    } 
    return os; 
} 

template <typename T> 
struct VectorN<T, 3> 
{ 
    union 
    { 
     T data[3]; 

     struct 
     { 
      T x, y, z; 
     }; 
    }; 
}; 

typedef VectorN<int, 3> Vec3i; 
typedef VectorN<float, 3> Vec3f; 

私はコンパイルしています主な機能は次のとおりです。

int main(int argc, char *argv[]) 
{ 
    Vec3f vec{ 0, 1, 2 }; 

    std::cout << vec << std::endl; 

    char dump; 
    std::cin >> dump; 
    std::cin.clear(); 

    return 0; 
} 

私はそれが動作することを期待するだろう、しかし、私はError: C2676 binary '[': 'const VectorN<float,3>' does not define this operator or a conversion to a type acceptable to the predefined operator

を取得

ostreamオペレータが意図したとおりに動作しているとは思いますが、i ndexing演算子はそうではありません。私がやっていることは明らかに間違っているのですか、あるいは現在のMSVCは単に私がしようとしていることをサポートしていませんか?

+0

特殊化は、基本テンプレートのメンバーにアクセスできません。継承元の共通基本クラスを作成することができます。 – DeiDei

答えて

1

あなたはdataxyz両方で3次元ベクトルにアクセスするためにunionベースのソリューションを維持したい場合は、派生クラスdataメンバーを認識している基本クラスを作成するためにCTRPを使用することができます:次のように

namespace impl 
{ 
    template <typename T, int n, typename TDerived> 
    struct VectorBase 
    { 
     const T& operator[](const int i) const 
     { 
      assert(i >= 0 && i < n); 
      return static_cast<const TDerived&>(*this).data[i]; 
     } 
    }; 
} 

あなたの派生クラスは、実装できます

template <typename T, int n> 
struct VectorN : impl::VectorBase<T, n, VectorN<T, n>> 
{ 
    T data[n]; 
}; 

template <typename T> 
struct VectorN<T, 3> : impl::VectorBase<T, 3, VectorN<T, 3>> 
{ 
    union 
    { 
     T data[3]; 

     struct 
     { 
      T x, y, z; 
     }; 
    }; 

    VectorN(T ax, T ay, T az) : data{ax, ay, az} {} 
}; 

working example is available on wandbox

+0

ありがとうございました!これは素晴らしいようです。ランタイムコストがないようにも見えますか?私はこれをテストする時間があるときにあなたに刻みを与えます。 –

+0

偉大な、完璧に動作します!私がしたいことをまだ維持している解決策を説明してくれてありがとうございます。 –

+0

Ah @ Vittorio-Romeo、これは私が分かりにくいことが一つありません。非const参照リターンを有効にするにはどうすればよいですか?私は価値を変更可能にしたいと思いますが、私がそれをしたら、再び問題にぶつかります。 最初に、constを削除すると 'const float'から 'float'に変換できません.2番目にstatic_castからconstを削除すると、元の投稿と同じ問題が発生します。 –

1

operator<<VectorNテンプレートタイプに対して適切なオーバーロードがあるためです。

operator[]は(親切にそれについてあなたに話すと、コンパイラ)は、特殊なVectorNのバージョンに存在しないため、他の側からは、operator[]は、は動作しません。

クラスの特殊バージョンにoperator[]を追加するか、前述の@DeiDeiのようにいくつかの機能を基本クラスに移動してください。

関連する問題