如何在类类型的模板类中定义静态模板变量?



我有以下代码

template<unsigned int n, class F, bool = std::floating_point<F>>
class Vector;
template<unsigned int n, class F>
class Vector<n, F, true> { //an n-dimensional vector
private:
F* components;
public:
Vector(F val) {
components = ::new F[n];
for (int i = 0; i < n; i++)
*(components + i) = val;
}
Vector(int index, F val) {
components = ::new F[n];
*(components + index) = val;
}
static const Vector ZERO;
static const Vector UNIT;
template<unsigned int m, bool = m <= n>
static const Vector UNIT_M; //a Vector<n, F>, with only one component being equal to 1.0
};
template<unsigned int n, class F>
static const Vector<n, F> ZERO{0.0};
template<unsigned int n, class F>
static const Vector<n, F> UNIT{1.0};
/*
template<unsigned int n, unsigned int m, class F>
static const Vector<n, F> UNIT_M{m, 1.0}; //How do I include the template above?
*/

我必须声明类Vector,然后只在std::floating_point<F>为真时才定义它。只有当m <= n && m != 0使用模板时,我才想对UNIT_M做同样的事情。0和UNIT都可以。

我提出另一种方法。我建议在类向量的私有部分创建一个助手类数组。类数组可以在编译时使用。你可以在下面的例子中找到我的评论。

#include <iostream>
#include <type_traits> // In this example I used std::is_floating_point instead of std::floating_point
template<unsigned int n, class F, bool = std::is_floating_point<F>::value>
class Vector;
template<unsigned int n, class F>
class Vector<n, F, true> { //an n-dimensional vector
private:
F* components = nullptr;

// Class Array is needed in order to have analogue of class Vector which can be used in compile time.
// Some constructors of class Vector can not be used in constant expressions because they refers to a result of 'operator new'.
class Array {
private:
F components [n] = {0}; // initialize all elements to 0
public:
constexpr Array(const F &val) {
for (size_t i = 0; i < n; i++) {
components[i] = val;
}
}
constexpr Array(const size_t &index, const F &val) {
components[index] = val;
}
constexpr ~Array() = default;

constexpr Array(const Array & other) = delete;
constexpr Array(Array && other) = delete;
Array& operator=(const Array & other) = delete;
Array& operator=(Array && other) = delete;

const F & operator[](const size_t &i) const {
return components[i];
}

Vector toVector() const {
return Vector(*this);
}
};

Vector(const Array &a) {
components = ::new F[n];
for (size_t i = 0; i < n; i++) {
components[i] = a[i];
}
}
public:
Vector(const F &val) {
components = ::new F[n];
for (size_t i = 0; i < n; i++) { // it is better to use size_t because it can be 8 bytes if the program is compiled for 64-bit system
components[i] = val;
}
}
Vector(const size_t &index, const F &val) {
components = ::new F[n];
components[index] = val;
}

// Don't forget about copy constructor
Vector(const Vector & other) {
components = ::new F[n];
for (size_t i = 0; i < n; i++) {
components[i] = other.components[i];
}
}

// Don't forget about move constructor
Vector(Vector && other) : components(other.components) {
other.components = nullptr;
}

// Don't forget about copy assignment operator
Vector& operator=(const Vector & other) {
if (this != &other) {
for (size_t i = 0; i < n; i++) {
components[i] = other.components[i];
}
}
return *this;
}

// Don't forget about move assignment operator
Vector& operator=(Vector && other) {
if (this != &other) {
delete[] components;
components = other.components;
other.components = nullptr;
}
return *this;
}

// Don't forget to free resourses
~Vector() {
delete[] components;
components = nullptr;
}

void print() const // const is important because static vectors are constant
{
for (unsigned int i = 0; i < n; i++) {
std::cout << components[i] << ' ';
}
std::cout << std::endl;
}
static const Vector ZERO;
static const Vector UNIT;
// Note, this instances of class Array are on the stack (not on the heap)
template<unsigned int m, std::enable_if_t< (m <= n), bool> = true>
static const Array UNIT_M;
};
template<unsigned int n, class F>
const Vector<n, F, true> Vector<n, F, true>::ZERO {0.0}; // define static const vector
template<unsigned int n, class F>
const Vector<n, F, true> Vector<n, F, true>::UNIT {1.0}; // define static const vector
template<unsigned int n, class F>
template<unsigned int m, std::enable_if_t< (m <= n), bool > = true>
const Vector<n, F, true>::Array Vector<n, F, true>::UNIT_M {m, 1.0};

int main()
{
Vector<4, double> myVector {5.0};
myVector.print();
myVector.ZERO.print();
myVector.UNIT.print();
myVector.UNIT_M<2>.toVector().print();
myVector.UNIT_M<3>.toVector().print();
// myVector.UNIT_M<10>.toVector().print();
return 0;
}

结果:

5 5 5 5 
0 0 0 0 
1 1 1 1 
0 0 1 0 
0 0 0 1 

最新更新