我想編寫我自己的Vector類模板,並且還想添加一些專業化,例如可以通過x/y/z訪問組件的3D矢量類型。C++模板專業化冗餘減少
到目前爲止,模板和專業化工作狀況良好,但問題是,專用模板需要從基本模板進行大量複製/粘貼才能正常工作。我想減少這一點。
這是它看起來像現在:
template<class T, unsigned int dim>
class Vector;
template<class T, unsigned int dim>
Vector<T, dim> add(Vector<T, dim> const& lhs, Vector<T, dim> const& rhs)
{
Vector<T, dim> tmp;
for (unsigned int i = 0; i < dim; ++i)
{
tmp[i] = lhs[i] + rhs[i];
}
return tmp;
}
template<class T, unsigned int dim, class S>
Vector<T, dim> add(Vector<T, dim> const& lhs, S const& rhs)
{
Vector<T, dim> tmp;
for (unsigned int i = 0; i < dim; ++i)
{
tmp[i] = lhs[i] + rhs;
}
return tmp;
}
template<class T, unsigned int dim>
Vector<T, dim> operator+(Vector<T, dim> const& lhs, Vector<T, dim> const& rhs)
{
return vectors::add(lhs, rhs);
}
template<class T, unsigned int dim, class S>
Vector<T, dim> operator+(Vector<T, dim> const& lhs, S const& rhs)
{
return vectors::add(lhs, rhs);
}
template<class T, unsigned int dim>
class Vector
{
//...
protected:
T values[dim] __attribute((aligned(16)));
public:
template<class R, unsigned int fdim>
friend Vector<R, fdim> operator+(Vector<R, fdim> const& lhs, Vector<R, fdim> const& rhs);
template<class R, unsigned int fdim, class S>
friend Vector<R, fdim> operator+(Vector<R, fdim> const& lhs, S const& rhs);
template<class R, unsigned int fdim, class S>
friend Vector<R, fdim> operator+(S const& lhs, Vector<R, fdim> const& rhs);
//...
//constructors, etc.
};
template<class T>
class Vector<T, 3>
{
//...
protected:
T values[3] __attribute((aligned(16)));
public:
T& x = values[0];
T& y = values[1];
T& z = values[2];
//lots of copy-pasta :(
template<class R, unsigned int fdim>
friend Vector<R, fdim> operator+(Vector<R, fdim> const& lhs, Vector<R, fdim> const& rhs);
template<class R, unsigned int fdim, class S>
friend Vector<R, fdim> operator+(Vector<R, fdim> const& lhs, S const& rhs);
template<class R, unsigned int fdim, class S>
friend Vector<R, fdim> operator+(S const& lhs, Vector<R, fdim> const& rhs);
//...
//constructors, etc.
};
現在我認爲最簡單的辦法是簡單地定義Vector3D
作爲一個子類Vector
模板的,就像這樣:
template<class T>
class Vector3D: public Vector<T, 3>
{
//...
public:
T& x = values[0];
T& y = values[1];
T& z = values[2];
//no copy-pasta :)
//...
//constructors, etc.
};
這並不在所有的工作中,由於不確定性:
ambiguous overload for ‘operator+’ (operand types are ‘const vec3f {aka const math::vectors::Vector3D<float>}’ and ‘math::vectors::vec3f {aka math::vectors::Vector3D<float>}’)
../main.cpp:84:16: note: candidates are:
In file included from ../main.cpp:10:0:
../include/vector.hpp:720:16: note: math::vectors::Vector<T, dim> math::vectors::operator+(const math::vectors::Vector<T, dim>&, const math::vectors::Vector<T, dim>&) [with T = float; unsigned int dim = 3u]
Vector<T, dim> operator+(Vector<T, dim> const& lhs, Vector<T, dim> const& rhs)
^
../include/vector.hpp:726:16: note: math::vectors::Vector<T, dim> math::vectors::operator+(const math::vectors::Vector<T, dim>&, const S&) [with T = float; unsigned int dim = 3u; S = math::vectors::Vector3D<float>]
Vector<T, dim> operator+(Vector<T, dim> const& lhs, S const& rhs)
^
../include/vector.hpp:732:16: note: math::vectors::Vector<T, dim> math::vectors::operator+(const S&, const math::vectors::Vector<T, dim>&) [with T = float; unsigned int dim = 3u; S = math::vectors::Vector3D<float>]
Vector<T, dim> operator+(S const& lhs, Vector<T, dim> const& rhs)
因此,看起來模板替換失敗了,因爲S也可以被新的Vector3D類替代,而它應該只處理標量。
於是,我就寫了標量小包裝類,像這樣擺脫這個問題的:
template<class T>
class ScalarType
{
public:
T value;
ScalarType() :
value(0)
{
}
ScalarType(T const& _v) :
value(_v)
{
}
ScalarType(ScalarType<T> const& rhs) :
value(rhs.value)
{
}
operator T&()
{
return value;
}
operator T() const
{
return value;
}
};
而且隨着ScalarType<S> const& (l|r)hs
取代的S const& (l|r)hs
所有實例。
讓操作符在兩側再次運行Vector,但是應該處理Vector-Scalar操作的操作符仍然失敗。
這次是因爲標量值必須顯式爲ScalarType
,因爲對其的隱式轉換不適用於模板替換。
那麼,有什麼辦法讓這個工作或我必須堅持複製粘貼代碼?
這是可能實現http://stackoverflow.com/questions/31449433/ generic-c-multidimensional-iterators/38510047#38510047 – slavanap
你做得太多了。有一個基類向量(值元組),並用循環實現操作(使用模板參數'dim')。然後(僅當性能和(!)編譯器生成的程序集不夠好時),請調整專門的模板。在任何情況下,都要在專門的模板中保留專門的功能(不要混淆基類) –
@DieterLücking,這就是計劃。這些操作符根本不是專用的,只是Vector類本身,而且僅僅是因爲我想通過Vector3D測試等簡單引用來訪問矢量組件; test.x = 12; 但是,當我只是專注於正常的方式,我不得不重新定義每個操作符超載或使用上面的朋友函數。 –