我在Visual Studio 2015社区版中使用最新版本的MSVC,我遇到了一些模板特化和运算符重载的问题。
我有以下(仅限标题)矢量类片段。我已经排除了不必要的代码(即vec2和vec4的相同特化)。
template <typename T, int n>
struct VectorN
{
T data[n];
T& operator[](const int i);
};
template <typename T, int n>
T& VectorN<T, n>::operator[](const int i)
{
static_assert(i >= 0 && i < n, "Index out of range");
return data[i];
}
template <typename T, int n>
std::ostream& operator<<(std::ostream& os, const VectorN<T, n>& vec)
{
for (auto i = 0; i < n; ++i)
{
os << vec[i];
}
return os;
}
具有以下专业化:
template <typename T>
struct VectorN<T, 3>
{
union
{
T data[3];
struct
{
T x, y, z;
};
};
};
typedef VectorN<int, 3> Vec3i;
typedef VectorN<float, 3> Vec3f;
我正在编译的主要功能是:
int main(int argc, char *argv[])
{
Vec3f vec{ 0, 1, 2 };
std::cout << vec << std::endl;
char dump;
std::cin >> dump;
std::cin.clear();
return 0;
}
我希望它有效,但是,我得到Error: C2676 binary '[': 'const VectorN<float,3>' does not define this operator or a conversion to a type acceptable to the predefined operator
我相信ostream运算符正在按预期工作,但索引运算符不是。有什么我正在做的那显然是错的,或者目前的MSVC根本不支持我想要做的事情?
答案 0 :(得分:1)
operator<<
有效,因为您对VectorN
模板类型进行了适当的重载。
另一方面,operator[]
不起作用,因为operator[]
的专用版本中没有VectorN
(编译器会告诉您它)。
您可以将operator[]
添加到VectorN
类的专用版本中,或者如@DeiDei所述,尝试将某些功能移至基类。
答案 1 :(得分:1)
如果您希望保持基于union
的解决方案,以便同时使用data
和x
,y
,z
来访问三维向量,您可以使用CTRP创建一个知道派生类的基类。 data
成员:
namespace impl
{
template <typename T, int n, typename TDerived>
struct VectorBase
{
const T& operator[](const int i) const
{
assert(i >= 0 && i < n);
return static_cast<const TDerived&>(*this).data[i];
}
};
}
您的派生类可以按如下方式实现:
template <typename T, int n>
struct VectorN : impl::VectorBase<T, n, VectorN<T, n>>
{
T data[n];
};
template <typename T>
struct VectorN<T, 3> : impl::VectorBase<T, 3, VectorN<T, 3>>
{
union
{
T data[3];
struct
{
T x, y, z;
};
};
VectorN(T ax, T ay, T az) : data{ax, ay, az} {}
};