2016-08-21 12 views
0

マトリックス<1,1>の変換をfloatに定義します。私は実際にそれを定義する方法を考え出すのに苦労します。私はそれグローバル関数特殊なテンプレートクラスの変換演算子を定義する

template<typename T> 
inline operator T(const matrix<T, 1, 1> &m){ return m(0, 0); } 

作る場合、私は取得「演算子を...非静的メンバ関数でなければなりません」

私はもちろん、一般的な行列テンプレートのメンバーとして定義することができますが、それは次のようになりますすべての行列に対して定義されています。これは私が望むものではありません。私は1x1行列の特定の場合にのみ定義したい。あなたはそのためのクラスを特化する必要が

+3

実際、 'operaror T()'変換関数はクラスメンバ関数である必要があります。それは単調で、パラメータを取ることはできません。しかし、テンプレート化された 'matrix'クラスのために特殊化を使うことができます。 –

答えて

4

は、例えば:

template <typename Base, typename T, std::size_t W, std::size_t H> 
struct MatrixConversion 
{ /*Empty*/ }; 

template <typename Base, typename T> struct MatrixConversion<T, 1u, 1u> 
{ 
    operator const T&() const { return static_cast<const Base&>(*this).m[0][0]; } 
}; 


template <typename T, std::size_t W, std::size_t H> 
struct Matrix : MatrixConversion<Matrix<T, W, H>, T, W, H> 
{ 
    // Your code 
}; 
+0

組成物の良好な使用。それは常に方法です。 +1 –

+0

@RichardHodges:ここでは*合成*ではなく、*継承*ではありません。 テンプレート<型名ベース、型名タイプ、サイズ_t M、size_tのN> 構造体MatrixToScalar {/:継承によって – Jarod42

+0

組成物は、次いで、 –

1

構図プラス専門は最も保守性のアプローチになります。

あなたは行列テンプレートクラスの次元数を指定していないので、私はそれが可変であると仮定しました。

#include <cstdint> 
#include <utility> 

// 
// forward-declare class template for convenience. 
// 
template<class T, std::size_t...Dimensions> 
struct matrix; 

// 
// classes to figure out the storage requirements of a multi-dimensional 
// matrix 
// 
template<class T, std::size_t...Dimensions> struct storage; 
template<class T, std::size_t N> 
    struct storage<T, N> 
    { 
    using type = T[N]; 
    }; 

template<class T, std::size_t...Rest, std::size_t N> 
    struct storage<T, N, Rest...> 
    { 
    using less_dimension_type = typename storage<T, Rest...>::type; 
    using type = less_dimension_type[N]; 
    }; 


// 
// functions for dereferencing multi-dimensional arrays 
// 
template<class Array, class Arg> 
decltype(auto) deref(Array& array, Arg&& arg) 
{ 
    return array[arg]; 
} 

template<class Array, class Arg, class Arg2> 
decltype(auto) deref(Array& array, Arg&& arg, Arg2&& arg2) 
{ 
    return array[arg][arg2]; 
} 

template<class Array, class Arg, class...Args> 
decltype(auto) deref(Array& array, Arg&& arg, Args&&...args) 
{ 
    return deref(deref(array, arg), std::forward<Args>(args)...); 
} 

// 
// prototype for operations we want to conditionally apply 
// 
template<class Matrix> 
struct matrix_conditional_ops 
{ 
    // in the general case, none 
}; 

// 
// compose the matrix class from conditional_ops<> 
//  
template<class T, std::size_t...Dimensions> 
struct matrix 
    : matrix_conditional_ops<matrix<T, Dimensions...>> 
{ 

    template<class...Dims> 
    decltype(auto) at(Dims&&...ds) 
    { 
     return deref(_data, std::forward<Dims>(ds)...); 
    } 

    template<class...Dims> 
    decltype(auto) at(Dims&&...ds) const 
    { 
     return deref(_data, std::forward<Dims>(ds)...); 
    } 

    typename storage<T, Dimensions...>::type _data; 
}; 

// 
// define the condition operations for the <T, 1, 1> case 
//  
template<class T> 
    struct matrix_conditional_ops<matrix<T, 1, 1>> 
    { 
    using matrix_type = matrix<T, 1, 1>; 

    operator T const() { return static_cast<matrix_type const&>(*this).at(0,0); } 
    }; 


int main() 
{ 
    matrix<double, 1, 1> m11; 

    m11.at(0,0) = 6.0; 
    double d = m11; 

    matrix<double, 2, 2> m22; 
    // compile error: 
// double d2 = m22; 

    // bonus points: 

    matrix<double, 3, 5, 2, 7> mxx; 
    mxx.at(2, 4, 1, 6) = 4.3; // probably needs some compile-time checking... 

} 

誰かが逆参照/梱包アレイのための私のロジックを確認したいことがあります...

+0

これはAlexandrescuの "Modern C++ Design"の読書の記憶を元に戻します。適切な言語の機械でタイプリストを処理します:) ** – StoryTeller

0

JarodRichardはすでにあなたに私の意見では最高の答えを与えた、彼らはすべてをオペレータの任意の数にうまくスケール種類の制限。

しかし、あなたはあなたのクラスを再設計する余裕がない、またはあなたが必要とするすべてが迅速かつ汚いopertor T()ある場合は、live hereで、次の

template<typename T, std::size_t N1, std::size_t N2> 
struct Matrix 
{ 
    T m[N1][N1]; 

    operator T() 
    { 
     static_assert(N1 == 1 && N2 == 1, "Only applicable to scalars"); 
     return m[0][0]; 
    } 
}; 

で逃げることができます。

+0

ローカルでのテストとリンクされたサンプルの両方がコンパイラエラーになります。あなたは実際にコンパイルするようにこの答えを編集できますか? – Martin

+0

@マーティン、どんなエラー?行列が '1x1'より大きい場合の失敗は意図的であることに留意されたい。 – StoryTeller

+0

@Martin、違反行を削除する(変換演算子を呼び出そうとする)と、[再生がうまくいく](http://ideone.com/FNLeTU) – StoryTeller

関連する問題