我正在嘗試為線性代數程式撰寫實用程式頭,它主要用于學習,所以我更關心的是易用性而不是效率。
無論如何,我的想法是我有一個Matrix型別,以及一個Vector繼承自Matrix. 因為我想添加一些專門針對 3D 情況的功能,而不重寫整個類,所以我還有一個_Vector類,它可以被通用型別和特殊型別繼承。
這是失敗的最小示例:(fails.hpp)
#include <string>
template <int M, int N, typename FloatType = double>
class Matrix {
public:
inline Matrix() : data{0}{}
protected:
FloatType data[M * N];
};
template <int DIM, typename FloatType>
class _Vector : public Matrix<DIM, 1, FloatType> {
public:
template <typename ...FloatTypes>
inline constexpr _Vector(const FloatTypes... values)
: Matrix<sizeof...(FloatTypes), 1, FloatType>()
{
int i = 0;
((Matrix<DIM, 1, FloatType>::data[i ] = values), ...);
}
inline FloatType operator [](const int index) {
return Matrix<DIM, 1, FloatType>::data[index];
}
inline operator std::string () const {
std::string tmp = "[ ";
for (int i = 0; i < DIM; i ) {
tmp = std::to_string(Matrix<DIM, 1, FloatType>::data[i]) " ";
}
tmp = "]\n";
return tmp;
}
};
template<int DIM, typename FloatType = double>
class Vector : _Vector<DIM, FloatType> {
template <typename ...FloatTypes>
inline constexpr Vector(const FloatTypes... values) : _Vector<DIM, FloatType>(values...) {}
};
template <typename ...FloatTypes>
Vector(const FloatTypes...) -> Vector<sizeof...(FloatTypes), std::common_type_t<FloatTypes...>>;
template <typename FloatType>
class Vector<3, FloatType> : public _Vector<3, FloatType> {
public:
FloatType& x = Matrix<3, 1, FloatType>::data[0];
FloatType& y = Matrix<3, 1, FloatType>::data[1];
FloatType& z = Matrix<3, 1, FloatType>::data[2];
template <typename ...FloatTypes>
inline constexpr Vector(const FloatTypes... values) : _Vector<3, FloatType>(values...) {}
// cross product
inline Vector operator ^(_Vector<3, FloatType>& other) {
Vector V;
V.x = y * other[2] - z * other[1];
V.y = z * other[0] - x * other[2];
V.z = x * other[1] - y * other[0];
return V;
}
};
(main.cpp)
#include <fails.hpp>
//#include <works.hpp>
#include <iostream>
int main() {
Vector v1 = { 1., 2., 3. };
Vector v2 = { 3., 2., 1. };
std::cout << (std::string)(v1 ^ v2);
}
我不明白的是,如果我從Matrix型別中洗掉繼承,它會解決問題:(works.hpp)
#include <string>
template <int DIM, typename FloatType>
class _Vector {
public:
template <typename ...FloatTypes>
inline constexpr _Vector(const FloatTypes... values)
{
int i = 0;
((data[i ] = values), ...);
}
inline FloatType operator [](const int index) {
return data[index];
}
inline operator std::string () const {
std::string tmp = "[ ";
for (int i = 0; i < DIM; i ) {
tmp = std::to_string(data[i]) " ";
}
tmp = "]\n";
return tmp;
}
protected:
FloatType data[DIM];
};
template<int DIM, typename FloatType = double>
class Vector : _Vector<DIM, FloatType> {
template <typename ...FloatTypes>
inline constexpr Vector(const FloatTypes... values) : _Vector<DIM, FloatType>(values...) {}
};
template <typename ...FloatTypes>
Vector(const FloatTypes...) -> Vector<sizeof...(FloatTypes), std::common_type_t<FloatTypes...>>;
template <typename FloatType>
class Vector<3, FloatType> : public _Vector<3, FloatType> {
public:
FloatType& x = Vector<3, FloatType>::data[0];
FloatType& y = Vector<3, FloatType>::data[1];
FloatType& z = Vector<3, FloatType>::data[2];
template <typename ...FloatTypes>
inline constexpr Vector(const FloatTypes... values) : _Vector<3, FloatType>(values...) {}
// cross product
inline Vector operator ^(_Vector<3, FloatType>& other) {
Vector V;
V.x = y * other[2] - z * other[1];
V.y = z * other[0] - x * other[2];
V.z = x * other[1] - y * other[0];
return V;
}
};
當我編譯時,g -I. main.cpp -std=c 17我得到這個輸出:
n file included from main.cpp:1:
./fails.hpp: In instantiation of ‘constexpr _Vector<DIM, FloatType>::_Vector(const FloatTypes ...) [with FloatTypes = {}; int DIM = 3; FloatType = double]’:
./fails.hpp:54:88: required from ‘Vector<3, FloatType> Vector<3, FloatType>::operator^(_Vector<3, FloatType>&) [with FloatType = double]’
main.cpp:9:35: required from here
./fails.hpp:58:12: in ‘constexpr’ expansion of ‘V.Vector<3, double>::Vector<>()’
./fails.hpp:16:51: error: type ‘Matrix<0, 1, double>’ is not a direct base of ‘_Vector<3, double>’
16 | : Matrix<sizeof...(FloatTypes), 1, FloatType>()
|
I don't know how the inheritance changed the situation at all but it now seems like the _Vector class constructor is called for some reason (with wrong template parameters at that). I don't know what to search for, so if you can explain why it causes this issue and in general what type of problem this is I'd be very grateful.
Thank you!
uj5u.com熱心網友回復:
你的_Vector<int DIM, typename FloatType>繼承Matrix<DIM, FloatType>,但它的建構式sizeof...(FloatTypes)用作的第一個模板引數Matrix
template <int DIM, typename FloatType>
class _Vector : public Matrix<DIM, 1, FloatType>
public:
template <typename ...FloatTypes>
constexpr _Vector(const FloatTypes... values)
: Matrix<sizeof...(FloatTypes), 1, FloatType>();
};
這意味著當DIM不等于時sizeof...(FloatTypes),您_Vector初始化一個不繼承自它的基,您應該將建構式定義為
template <typename ...FloatTypes>
constexpr _Vector(const FloatTypes... values)
: Matrix<DIM, 1, FloatType>();
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/438340.html
標籤:c templates matrix c 17 linear-algebra
