对于模板等练习,我正在为任意数字维度实现固定大小的模板数学类型。
前提: 我有一个基础 rvec 类,用于抽象实现向量数学的 tvec 类(未显示或必需)所使用的数据。基类有两种形式 - 值类型和引用类型,通过使用布尔标志的模板特化来区分。
引用类型是我目前实现任意调配的解决方案。我正在使用traits来根据类型(指针或非指针)启用/禁用重载,但这对于我的混合所需的可变参数的部分特化效果不佳(它确实有效,但需要滥用特性和模板到我觉得自己并不能保持这种程度 - 我可以回到那个程度。)
问题:以下内容完全符合预期!有一件事真的让我烦恼。创建自动变量并将其分配给swizzle时,它会存储引用类型而不是存储value-type。我真的不希望最终用户能够创建引用类型。此数据结构应尽可能模拟或表现为POD。
仅存在引用类型,因此我可以从混合中进行方法链接。可悲的是,如果不使用汽车,一切正常。
template<unsigned S, typename T=float, bool B=false>
class rvec
{
std::array<T, S> data;
public:
float operator[] (unsigned i) const { return data[i]; }
float &operator[] (unsigned i) { return data[i]; }
// Returns reference-type!
template<unsigned ...I, unsigned N = sizeof...(I)>
rvec<N, T, true> swizzle() { return{ {&data[I]...} }; }
// Value-Type!
template<unsigned ...I, unsigned N = sizeof...(I)>
rvec<N, T> swizzle() const { return{ { data[I]... } }; }
rvec(const std::initializer_list<T> &d) { std::copy(d.begin(), d.end(), data.begin()); }
rvec() {}
};
这是我的参考类型。它应该提供读取和写入,但我不希望用户有意或无意地将其存储在变量中。它应该只存在于方法链变化到调用swizzle的值类型。
我尝试对赋值/复制构造函数进行私有化,但编译器不会切换到使用正确的混合函数(来自value-type)或利用隐式类型转换(在reference-type中)。
template<unsigned S, typename T>
class rvec<S,T,true>
{
std::array<T*, S> data;
rvec(const std::initializer_list<T*> &d) { std::copy(d.begin(), d.end(), data.begin()); }
template<unsigned N, typename T, bool B> friend class rvec;
rvec &operator=(const rvec &o);
rvec(const rvec &o);
public:
// same access behavior as value-type
float operator[] (unsigned i) const { return *data[i]; }
float &operator[] (unsigned i) { return *data[i]; }
// convert to value-type.
operator rvec<S, T, false>()
{
rvec<S, T, false> r;
for (unsigned i = 0; i < S; ++i)
r[i] = *data[i];
return r;
}
// write to the original values
rvec &operator=(const rvec<S, T, false> &o)
{
for (unsigned i = 0; i < S; ++i)
&data[i] = o[i];
}
template<unsigned ...I, unsigned N = sizeof...(I)>
rvec<N, T, true> swizzle() const { return{ { data[I]... } }; }
};
什么是阻止我的参考类型出现在混合之外的好方法?我需要写访问权限并希望保持固定大小。
谢谢!