模板成员转换运算符,默认模板参数到与 TypeName 绑定的函数

template member conversion operator with default template argument to the function that bind with typename

本文关键字:TypeName 函数 绑定 默认 成员 转换 运算符 参数      更新时间:2023-10-16
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) ;

所以这是我的问题,为什么我的转换运算符不起作用?是否有适合此数学向量类的其他转换形式?

问题是你的_Prd(谓词?)模板参数。 转换运算符定义为

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

这意味着元素类型U可以不同于要从中转换的向量的元素类型T,但谓词类型必须匹配。 在您的代码中,您使用的是默认谓词std::equal_to<T>,这对于您的两种类型是不同的,即您正在尝试转换

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 ;