code: vectorBase.hpp:一些低维特化、 #include <iostream> using namespace std; // for any dimensions other than // specified below, this struct will // be used template<class T,int N> struct vector_base { T m_data[N]; }; // specialization for a 2D vector // provides the vector with .x and .y variables template<class T> struct vector_base<T, 2> { union { struct { T x, y; }; T m_data[2]; }; vector_base() { } vector_base( const T& _x, const T& _y ) : x(_x), y(_y) { } }; // specialization for a 3D vector // provides the vector with .x, .y, and .z variables template<class T> struct vector_base<T,3> { union { struct { T x, y, z; }; T m_data[3]; }; vector_base() { } vector_base( const T& _x, const T& _y, const T& _z ) : x(_x), y(_y), z(_z) { } }; // specialization for a 4D vector // provides the vector with .w, .x, .y, and .z variables template<class T> struct vector_base<T,4> { union { struct { T w, x, y, z; }; T m_data[4]; }; vector_base() { } vector_base( const T& _w, const T& _x, const T& _y, const T& _z ) : w(_w), x(_x), y(_y), z(_z) { } }; // a base for a vector that doesn't specialize vector_base // provides the vector with .r, .g, .b, and .a variables template<class T> struct vector_color { union { struct { T r, g, b, a; }; T m_data[4]; }; vector_color() { } vector_color( const T& _r, const T& _g, const T& _b, const T& _a ) : r(_r), g(_g), b(_b), a(_a) { } }; vectorTemplate.hpp 类的定义实现: #include <cassert> #include <cmath> #include "vectorBase.hpp" // the vector itself // with its variable type: T // its dimensions: N // and its core: base template<class T, int N, class base = vector_base<T,N> > class vector_t : public base { public: // handy typedef: typedef vector_t<T,N> my_type; // default constructor vector_t() { } // two-arg constructor for 2D vectors vector_t( const T& x, const T& y ) : base(x,y) { } // three-arg constructor for 3D vectors vector_t( const T& x, const T& y, const T& z ) : base(x,y,z) { } // four-arg constructor for 4D vectors vector_t( const T& w, const T& x, const T& y, const T& z ) : base(w,x,y,z) { } // // Note, if the programmer tries to construct a 3D vector using a two-arg constructor, // the compiler will complain that base does not have enough arguments. Nifty :) // // constructor for same-dimensional, differing-typed vectors // use the keyword "explicit" template<class T2, class B2> vector_t( const vector_t<T2,N,B2>& rhs ) { for ( int i = 0; i < N; i++ ) m_data[i] = static_cast<T>( rhs.m_data[i] ); } // constructor with a same-dimensional array of a differing type template<class T2> // vector_t( const T2 data[N] ) vector_t( const T2 (&data)[N] ) { for ( int i = 0; i < N; i++ ) m_data[i] = static_cast<T>( data[i] ); } // assignment operation for same-dimensional, differing-typed vectors template<class T2, class B2> my_type& operator = ( const vector_t<T2,N,B2>& rhs ) { for ( int i = 0; i < N; i++ ) m_data[i] = static_cast<T>( rhs.m_data[i] ); return *this; } // assignment operation for a an array of a differing type template<class T2> my_type& operator = ( const T2 data[N] ) { for ( int i = 0; i < N; i++ ) m_data[i] = static_cast<T>( data[i] ); return *this; } // // getters // T& operator [] ( const int idx ) { assert( 0 <= idx && idx < N ); // or throw an exception return m_data[ idx ]; } const T& operator [] ( const int idx ) const { assert( 0 <= idx && idx < N ); return m_data[ idx ]; } // // overloads // // negation my_type operator - () const { my_type result; for ( int i = 0; i < N; i++ ) result.m_data[i] = -m_data[i]; return result; } // addition of two same-dimensional, differing-typed vectors template<class T2,class B2> my_type operator + ( const vector_t<T2,N,B2>& rhs ) const { my_type result; for ( int i = 0; i < N; i++ ) result.m_data[i] = m_data[i] + rhs.m_data[i]; return result; } // subtraction of two same-dimensional, differing-typed vectors template<class T2,class B2> my_type operator - ( const vector_t<T2,N,B2>& rhs ) const { my_type result; for ( int i = 0; i < N; i++ ) result.m_data[i] = m_data[i] - rhs.m_data[i]; return result; } // scalar multiplication of two same-dimensional, differing-typed vectors template<class T2> my_type operator * ( const T2& rhs ) const { my_type result; for ( int i = 0; i < N; i++ ) result.m_data[i] = static_cast<T>( m_data[i] * rhs ); return result; } // scalar division of two same-dimensional, differing-typed vectors template<class T2> my_type operator / ( const T2& rhs ) const { my_type result; for ( int i = 0; i < N; i++ ) result.m_data[i] = m_data[i] / rhs; return result; } // // operations: // // calculate the dot product of two differing-typed vectors template<class T2,class B2> T dot( const vector_t<T2,N,B2>& rhs ) const { T result = static_cast<T>( 0 ); for ( int i = 0; i < N; i++ ) result += static_cast<T>( m_data[i] * rhs.m_data[i] ); return result; } // squared length of the vector T length_sq() const { return this->dot( *this ); } // length of the vector T length() const { return std::sqrt( this->dot( *this ) ); } // return a normalized vector my_type normalize() const { return *this / this->length(); } // and for other operations not mentioned, // you can provide a functor to do the rest template<class F> my_type predicate( const F& f ) const { my_type result; for ( int i = 0; i < N; i++ ) result.m_data[i] = f( m_data[i] ); return result; } }; // handy write to ostream function: template<class T, int N, class B> std::ostream& operator << ( std::ostream& out, const vector_t<T,N,B>& v ) { for ( int i = 0; i < N; i++ ) out << v.m_data[ i ] << ' '; return out; } 测试程序: main.cpp #include "TemplateFunctionVector.hpp" #include "vectorTemplate.hpp" int main( int c, char* v[] ) { // // the vector_t declaration is already looking ugly, // provide some typedefs: // // simple geometric types: typedef vector_t<double,2> v2; typedef vector_t<int,2> v2i; // graphics specific color types: typedef unsigned char ui8; typedef vector_t<float, 4, vector_color<float> > colorf; typedef vector_t<int, 4, vector_color<int> > colori; typedef vector_t<ui8, 4, vector_color<ui8> > color; // // begin some tests: // // // test 1: // { std::cout << "test1:/n"; v2 pt1_d = v2( 3.0, 3.0 ); v2i pt2_i( 1, 2 ); v2 pt2 = (pt1_d + pt2_i) * 0.5; std::cout << pt2 << "/n/n"; } // // test 2: // { std::cout << "test2:/n"; // v2 pt1 = v2( 1.0, 2.0, 3.0 ); // C2661: no overloaded function takes three arguments v2 pt1 = v2( 1.0, 2.0 ); v2i pt2i = v2i( 3, 4 ); v2 pt3( pt1 ); // test copy constructor std::cout << pt3 << '/n'; pt3 = pt1; // test assignment operator std::cout << pt3 << '/n'; pt3 = pt2i; // test assignment operator std::cout << pt3 << '/n'; pt3.y = pt3.x; // test aliases std::cout << "/n/n"; } // // test 3: // { std::cout << "test3:/n"; colorf my_color( 0.0, 1.0, 0.5, 1.0 ); std::cout << my_color << '/n'; // test alias: my_color.r = 0.25; std::cout << my_color << '/n'; color hardware_color( my_color * 255 ); std::cout << colori( hardware_color ) << '/n'; // cast to int to display ints instead of chars std::cout << "/n/n"; } // // test 4: // { std::cout << "test4:/n"; typedef vector_t<double,5> v5; // vector_t doesn't have a five arg constructor, so // we will have to use arrays, (or just implement a 5-arg constructor) double arr[] = { 1.0, 2.0, 3.0, 4.0, 5.0 }; v5 p1( arr ); v5 p2 = arr; std::cout << p1 << '/n' << p2 << '/n' << (p1 + p2).normalize() << '/n'; // v5 p3( { 1.0, 2.0, 3.0, 4.0, 5.0 } ); // error :( std::cout << "/n/n"; } system("PAUSE"); return 0; } 测试输出: test1: 2 2.5 test2: 1 2 1 2 3 4 test3: 0 1 0.5 1 0.25 1 0.5 1 63 255 127 255 test4: 1 2 3 4 5 1 2 3 4 5 0.13484 0.26968 0.40452 0.53936 0.6742 请按任意键继续. . .