1
template<typename T, int cn, typename _Prd = equal_to<T> > //watch out this <T>, when convert it to other typename, _Prd changes too.
struct Vec
{
//output overloading
// c++ gotcha, must forward declare this, and with <> .
friend std::ostream& operator<< <>(std::ostream& output, const Vec<T,cn,_Prd>& out);
friend const Vec<T,cn,_Prd> operator+ <>(const Vec<T,cn,_Prd>& lhs, const Vec<T,cn,_Prd>& rhs) ;
friend const Vec<T,cn,_Prd> operator+ <>(const T& lhs, const Vec<T,cn,_Prd>& rhs)  ;
friend const Vec<T,cn,_Prd> operator+ <>(const Vec<T,cn,_Prd>& lhs, const T& rhs)  ;

friend const Vec<T,cn,_Prd> operator- <>(const Vec<T,cn,_Prd>& lhs, const Vec<T,cn,_Prd>& rhs) ;
friend const Vec<T,cn,_Prd> operator- <>(const T& lhs, const Vec<T,cn,_Prd>& rhs)  ;
friend const Vec<T,cn,_Prd> operator- <>(const Vec<T,cn,_Prd>& lhs, const T& rhs)  ;

friend const Vec<T,cn,_Prd> operator* <>(const T& lhs, const Vec<T,cn,_Prd>& rhs)  ;
friend const Vec<T,cn,_Prd> operator* <>(const Vec<T,cn,_Prd>& lhs, const T& rhs)  ;


protected:
    T data[cn] ;
    _Prd comp ;
public:
    typedef T value_type ;

    Vec() ;
    Vec(T v0, T v1) ;
    Vec(T v0, T v1, T v2) ;
    Vec(T v0, T v1, T v2, T v3) ;
    explicit Vec(const T* values) ;
    explicit Vec(const T& value) ;


    //copy constructor, incase delete twice
    Vec(const Vec<T, cn, _Prd>& v) ;

    //Get Magnituede
    T magnituede() const ;
    //Dot product
    T dot(const Vec<T, cn, _Prd>& b) const ;

    //cross product of two 3D vectors, other dimension raises exception
    Vec<T, cn, _Prd>& cross(const Vec<T, cn, _Prd>& v) const ;

    //product of all elements
    T product() ;

    //scale vector to 1
    Vec<T, cn, _Prd>& normalize() ;
    Vec<T,cn,_Prd> normalize(const Vec<T,cn,_Prd>& rhs) ;
    //change length of the vector
    Vec<T, cn, _Prd>& scale(const T &length);
    Vec<T, cn, _Prd> scale(const Vec<T,cn,_Prd> &rhs,const T &length) ;

    //project
    Vec<T, cn, _Prd> projectTo (const Vec<T,cn,_Prd>& rhs) ;

    //Operators

    //element access
    const T& operator[](const int& i) const ;
    T& operator[](const int& i) ;

    //return element number
    T GetSize() ;

    //comparison 
    bool operator==(const Vec<T,cn,_Prd>& rhs) const ;
    bool operator!=(const Vec<T,cn,_Prd>& rhs) const ;

    //function call operators
    Vec<T,cn,_Prd>& operator() (const T* rhs) ;
    Vec<T,cn,_Prd>& operator() (const Vec<T,cn,_Prd>& rhs );

    //assignment
    Vec<T,cn,_Prd>& operator=(const Vec<T,cn,_Prd>& rhs) ; //care, here is no copy
    Vec<T,cn,_Prd>& operator=(const T rhs[cn]) ;
    Vec<T,cn,_Prd> operator=(const T& rhs) ; //assignment constructor
    Vec<T,cn,_Prd> operator-() const;

    //math

    Vec<T,cn,_Prd>& operator+=(const Vec<T,cn,_Prd>& rhs) ;
    Vec<T,cn,_Prd>& operator+=(const T& rhs) ;

    Vec<T,cn,_Prd>& operator-=(const Vec<T,cn,_Prd>& rhs) ;
    Vec<T,cn,_Prd>& operator-=(const T& rhs) ;

    Vec<T,cn,_Prd>& operator*=(const T& rhs) ;

    static Vec<T, cn, _Prd> abs(const Vec<T,cn,_Prd>& rhs) ;    
    static void swap(Vec<T,cn,_Prd>& a,Vec<T,cn,_Prd>& b) ;

    //conversion
    template<typename U> operator Vec<U,cn,_Prd> () const ;

};

この変換演算子は私を夢中にさせます。

template<typename U> operator Vec<U,cn,_Prd> () const ;

実装は次のとおりです。

//conversion
template<typename T, int cn, typename _Prd>
template<typename U> 
Vec<T,cn,_Prd>::operator Vec<U,cn,_Prd> () const 
{
  U temp[cn] ;
  for (int i = 0 ; i < cn ; ++i)
      temp[i] = static_cast<U>(this->data[i]) ;
  Vec<U,cn,_Prd> v(temp) ;
  return v ;
};

inline void foo (Vec<int,2> test)
{
    std::cout <<"works" << std::endl ;
}

そして、呼び出しは次のとおりです。

Vec<double,2> vec25(234.5,2352.5) ;
foo(vec25) ;
Vec<int,2> vec26 = Vec<int,2>(vec25) ;

エラーは次のとおりです。

tests/newsimpletest1.cpp:74: error: conversion from ‘Vec<double, 2, std::equal_to<double> >’ to non-scalar type ‘Vec<int, 2, std::equal_to<int> >’ requested
tests/newsimpletest1.cpp:75: error: no matching function for call to ‘Vec<int, 2, std::equal_to<int> >::Vec(Vec<double, 2, std::equal_to<double> >&)’
./Vec.hpp:186: note: candidates are: Vec<T, cn, _Prd>::Vec(const Vec<T, cn, _Prd>&) [with T = int, int cn = 2, _Prd = std::equal_to<int>]
./Vec.hpp:180: note:                 Vec<T, cn, _Prd>::Vec(const T&) [with T = int, int cn = 2, _Prd = std::equal_to<int>]
./Vec.hpp:173: note:                 Vec<T, cn, _Prd>::Vec(const T*) [with T = int, int cn = 2, _Prd = std::equal_to<int>]
./Vec.hpp:166: note:                 Vec<T, cn, _Prd>::Vec(T, T, T, T) [with T = int, int cn = 2, _Prd = std::equal_to<int>]
./Vec.hpp:159: note:                 Vec<T, cn, _Prd>::Vec(T, T, T) [with T = int, int cn = 2, _Prd = std::equal_to<int>]
./Vec.hpp:149: note:                 Vec<T, cn, _Prd>::Vec(T, T) [with T = int, int cn = 2, _Prd = std::equal_to<int>]
./Vec.hpp:145: note:                 Vec<T, cn, _Prd>::Vec() [with T = int, int cn = 2, _Prd = std::equal_to<int>]

ただし、別のプロジェクトで試してみましたが、動作します。

template <typename T>
class varmani
{
    T var ;
    public:
        varmani (T var_){
            var = var_ ;
        }
        T increase() {
            return ++var ;
        }
        template<typename U> operator varmani<U> () const;

};

void foo (varmani<int> test)
{
    std::cout << "works" << std::endl ;
}

template <typename T>
template <typename U>
varmani<T>::operator varmani<U> () const
{

   U temp = static_cast<U>(this->var) ;
   varmani<U> v(temp) ;
   return v ;
}

//all works
varmani<double> test3(10.25) ; 
varmani<int> test4 = varmani<int>(test3) ;
foo(test3) ;

ここに私の質問があります。変換演算子が機能しないのはなぜですか? この数学ベクトル クラスに適した他の変換形式はありますか?

4

1 に答える 1

3

問題は、_Prd(述語?) テンプレート引数です。変換演算子は次のように定義されます。

template<typename U> operator Vec<U,cn,_Prd> () const ;

つまり、要素の型は、変換元のベクトルUの要素の型とは異なる可能性がありTますが、述語の型は一致する必要があります。コードではデフォルトの述語を使用していますがstd::equal_to<T>、これは 2 つのタイプで異なります。つまり、変換しようとしています。

Vec<double, 2, std::equal_to<double>>

Vec<int, 2, std::equal_to<int>>.

これがコンパイラ エラーの原因です。このタイプの変換を許可する場合は、別のテンプレート引数を変換関数に追加する必要があります。

template<typename U, typename Prd2> operator Vec<U,cn,Prd2> () const ;
于 2012-11-14T00:34:15.847 に答える