Vector class 的专用构造函数
Specialised constructor for Vector class
我正在尝试编写一个数学向量 class。第一个版本是这样的:
template <typename T, unsigned int n>
struct Vector {
Vector<T, n>(T t = T()) // default
{
for (int i = 0; i < n; i++)
{
data[i] = t;
}
}
Vector<T, n>(const Vector<T, n> &aVector)
{
for (unsigned int i = 0; i < n; i++)
{
data[i] = aVector.data[i];
}
}
Vector<T, n>(const T arr[n])
{
for (unsigned int i = 0; i < n; i++)
{
data[i] = arr[i];
}
}
T& operator[](unsigned int i);
const T& operator[](unsigned int i) const;
Vector<T, n>& operator=(const Vector<T, n> &aVector);
void normalise();
T data[n];
};
我还有在 class 之外声明的运算符(+、* 等),以及其他几个 classes.
事情是这样的。对于长度为 2、3、4 的向量,我想要一个以 x,y(对于 Vec2)、x,y,z 或 x,y,z,w 作为参数的构造函数(或函数)。
但是,您似乎无法为此目的制作专门的构造函数。在这种情况下我应该如何进行?我是否必须完全专门化三种情况?这是否意味着我必须重写代码块?
我也有一个类似的 Matrix class (Matrix),我很确定我需要一些构造函数来进行旋转、平移、缩放等。我假设我需要克服了类似的问题。
如果你看到
我还在 class 之外声明了运算符(+、* 等),以及一些其他函数(点、十字等)。
事情是这样的。对于长度为 2、3、4 的向量,我想要一个以 x,y(对于 Vec2)、x,y,z 或 x,y,z,w 作为参数的构造函数(或函数)。
但是,您似乎无法为此目的制作专门的构造函数。在这种情况下我应该如何进行?我是否必须完全专门化三种情况?这是否意味着我必须重写代码块?
我也有一个类似的 Matrix class (Matrix),我很确定我需要一些构造函数来进行旋转、平移、缩放等。我假设我需要克服了类似的问题。
如果您在代码中看到任何您认为不对的地方,请随时指出。
编辑:如果我不够清楚,数组应该是一维的,并且它的所有组件都是同一类型。专业化适用于具有 2、3 和 4 个元素的数组。
就个人而言,我会为每个向量声明不同的 classes。 Vec2<T1, T2>
、Vec3<T1, T2, T3>
和 Vec4<T1, T2, T3, T4>
。使每个 Vec*
class 公开继承一个未模板化的基础 class Vector
,然后在 Vector
中创建一个带有重载的静态函数 create
对于将负责创建它们的每个 Vec*
类型。 Vec3
的伪示例:
template<T1, T2, T3> static std::shared_ptr<Vector> create(T1 a1, T2 a2, T3 a3)
{
return new Vec3<T1, T2, T3>(a1, a2, a3);
}
auto vec = Vector::create<int, int, int>(1, 2, 3);
可变模板和 SFINAE 可以解决这个问题。
但我认为更简单的方法是从(专门的)helper
继承
template <typename T, unsigned int n>
struct VectorHelper<T, n>
{
T data[n];
};
template <typename T>
struct VectorHelper<T, 2>
{
VectorHelper(T x, T y) : {data[0] = x; data[1] = y;}
T data[2];
};
template <typename T>
struct VectorHelper<T, 3>
{
VectorHelper(T x, T y, T z) : {data[0] = x; data[1] = y; data[2] = z}
T data[3];
};
template <typename T, unsigned int n>
struct Vector : private VectorHelper<T, n>
{
using VectorHelper<T, n>::VectorHelper; // use base constructor(s)
// your previous implementation without `data` (as member of base)
};
您可以使用可变参数模板:
#include <chrono>
#include <future>
#include <iostream>
#include <stdexcept>
template<typename T, unsigned int n>
struct Vector
{
// Note: We need x and y:
// The default (in the question) is a constructor taking a single argument.
template <typename ... Args>
Vector(T x, T y, Args ... args)
{
static_assert(sizeof ... (Args) == n - 2, "Invalid number of arguments");
auto initializer_list = { x, y, std::forward<Args>(args)... };
std::copy(initializer_list.begin(), initializer_list.end(), data);
}
T data[n];
};
template<typename T, unsigned int n>
void print(const Vector<T, n>& v) {
for(unsigned i = 0; i < n; ++i)
std::cout << v.data[i] << ' ';
std::cout << '\n';
}
int main()
{
Vector<int, 2> v2(1, 2);
Vector<int, 3> v3(1, 2, 3);
Vector<int, 4> v4(1, 2, 3, 4);
print(v2);
print(v3);
print(v4);
// Invalid number of arguments
// Vector<int, 3> e2(1, 2);
// Invalid number of arguments
// Vector<int, 3> e4(1, 2, 3, 4);
return 0;
}
我正在尝试编写一个数学向量 class。第一个版本是这样的:
template <typename T, unsigned int n>
struct Vector {
Vector<T, n>(T t = T()) // default
{
for (int i = 0; i < n; i++)
{
data[i] = t;
}
}
Vector<T, n>(const Vector<T, n> &aVector)
{
for (unsigned int i = 0; i < n; i++)
{
data[i] = aVector.data[i];
}
}
Vector<T, n>(const T arr[n])
{
for (unsigned int i = 0; i < n; i++)
{
data[i] = arr[i];
}
}
T& operator[](unsigned int i);
const T& operator[](unsigned int i) const;
Vector<T, n>& operator=(const Vector<T, n> &aVector);
void normalise();
T data[n];
};
我还有在 class 之外声明的运算符(+、* 等),以及其他几个 classes.
事情是这样的。对于长度为 2、3、4 的向量,我想要一个以 x,y(对于 Vec2)、x,y,z 或 x,y,z,w 作为参数的构造函数(或函数)。
但是,您似乎无法为此目的制作专门的构造函数。在这种情况下我应该如何进行?我是否必须完全专门化三种情况?这是否意味着我必须重写代码块?
我也有一个类似的 Matrix class (Matrix),我很确定我需要一些构造函数来进行旋转、平移、缩放等。我假设我需要克服了类似的问题。
如果你看到
我还在 class 之外声明了运算符(+、* 等),以及一些其他函数(点、十字等)。
事情是这样的。对于长度为 2、3、4 的向量,我想要一个以 x,y(对于 Vec2)、x,y,z 或 x,y,z,w 作为参数的构造函数(或函数)。
但是,您似乎无法为此目的制作专门的构造函数。在这种情况下我应该如何进行?我是否必须完全专门化三种情况?这是否意味着我必须重写代码块?
我也有一个类似的 Matrix class (Matrix),我很确定我需要一些构造函数来进行旋转、平移、缩放等。我假设我需要克服了类似的问题。
如果您在代码中看到任何您认为不对的地方,请随时指出。
编辑:如果我不够清楚,数组应该是一维的,并且它的所有组件都是同一类型。专业化适用于具有 2、3 和 4 个元素的数组。
就个人而言,我会为每个向量声明不同的 classes。 Vec2<T1, T2>
、Vec3<T1, T2, T3>
和 Vec4<T1, T2, T3, T4>
。使每个 Vec*
class 公开继承一个未模板化的基础 class Vector
,然后在 Vector
中创建一个带有重载的静态函数 create
对于将负责创建它们的每个 Vec*
类型。 Vec3
的伪示例:
template<T1, T2, T3> static std::shared_ptr<Vector> create(T1 a1, T2 a2, T3 a3)
{
return new Vec3<T1, T2, T3>(a1, a2, a3);
}
auto vec = Vector::create<int, int, int>(1, 2, 3);
可变模板和 SFINAE 可以解决这个问题。 但我认为更简单的方法是从(专门的)helper
继承template <typename T, unsigned int n>
struct VectorHelper<T, n>
{
T data[n];
};
template <typename T>
struct VectorHelper<T, 2>
{
VectorHelper(T x, T y) : {data[0] = x; data[1] = y;}
T data[2];
};
template <typename T>
struct VectorHelper<T, 3>
{
VectorHelper(T x, T y, T z) : {data[0] = x; data[1] = y; data[2] = z}
T data[3];
};
template <typename T, unsigned int n>
struct Vector : private VectorHelper<T, n>
{
using VectorHelper<T, n>::VectorHelper; // use base constructor(s)
// your previous implementation without `data` (as member of base)
};
您可以使用可变参数模板:
#include <chrono>
#include <future>
#include <iostream>
#include <stdexcept>
template<typename T, unsigned int n>
struct Vector
{
// Note: We need x and y:
// The default (in the question) is a constructor taking a single argument.
template <typename ... Args>
Vector(T x, T y, Args ... args)
{
static_assert(sizeof ... (Args) == n - 2, "Invalid number of arguments");
auto initializer_list = { x, y, std::forward<Args>(args)... };
std::copy(initializer_list.begin(), initializer_list.end(), data);
}
T data[n];
};
template<typename T, unsigned int n>
void print(const Vector<T, n>& v) {
for(unsigned i = 0; i < n; ++i)
std::cout << v.data[i] << ' ';
std::cout << '\n';
}
int main()
{
Vector<int, 2> v2(1, 2);
Vector<int, 3> v3(1, 2, 3);
Vector<int, 4> v4(1, 2, 3, 4);
print(v2);
print(v3);
print(v4);
// Invalid number of arguments
// Vector<int, 3> e2(1, 2);
// Invalid number of arguments
// Vector<int, 3> e4(1, 2, 3, 4);
return 0;
}