向量运算符和类型转换
vector operators and type conversions
我正在创建一个数学向量类。
我希望它的运营商提供类型之间的转换/警告行为,类似于转换如何与 POD 类型一起工作C++,例如:
//{
// auto f = 1.f;
// auto d = 2.0;
// f *= d; // warns about possible loss of data
// d *= f; // fine
// auto d2 = f * d; // fine (f promotion, d2 is double)
//}
据我了解,我需要使用 std::common_type 来找到正确的类型。不幸的是,我收到编译器错误,例如:
1>C:Program Files (x86)Microsoft Visual Studio 12.0VCincludetype_traits(1446): error C2446: ':' : no conversion from 'Testing::Vector<float,3>' to 'float'
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1> TestVector.cpp(152) : see reference to class template instantiation 'std::common_type<float,Testing::Vector<float,3>>' being compiled
以下是相关代码:
template<class ElementT, unsigned int Dimensions>
class Vector
{
public:
typedef ElementT ElementT;
static const unsigned int Dimensions = Dimensions;
typedef std::array<ElementT, Dimensions> DataT;
Vector():
data() { }
explicit Vector(std::initializer_list<ElementT> values):
data()
{
std::copy(values.begin(), values.end(), data.begin());
}
template<class E>
explicit Vector(Vector<E, Dimensions> const& other):
data()
{
std::copy(other.Data().begin(), other.Data().end(), data.begin());
}
Vector& operator*=(ElementT value)
{
for (auto& e : data)
e *= value;
return *this;
}
Vector& operator*=(Vector const& other)
{
for (auto i = 0u; i != data.size(); ++i)
data[i] *= other.data[i];
return *this;
}
// etc. ...
// Warnings are still propagated from the copy constructor
// if this is used with inappropriate types...
template<class E>
operator Vector<E, Dimensions>() const
{
return Vector<E, Dimensions>(*this);
}
DataT& Data()
{
return data;
}
DataT const& Data() const
{
return data;
}
private:
friend std::ostream& operator<<(std::ostream& stream, Vector v)
{
for (auto const& e : v.data)
stream << e << " ";
return stream;
}
DataT data;
};
template<class E, unsigned int D>
Vector<E, D> operator*(Vector<E, D> const& v, E value)
{
auto result = Vector<E, D>(v);
result *= value;
return result;
}
template<class E, unsigned int D>
Vector<E, D> operator*(Vector<E, D> const& v1, Vector<E, D> const& v2)
{
auto result = Vector<E, D>(v1);
result *= v2;
return result;
}
template<class E, class T, unsigned int D>
Vector<std::common_type_t<E, T>, D> operator*(Vector<E, D> const& v, T value)
{
auto result = Vector<std::common_type_t<E, T>, D>(v);
result *= value;
return result;
}
template<class E1, class E2, unsigned int D>
Vector<std::common_type_t<E1, E2>, D> operator*(Vector<E1, D> const& v1, Vector<E2, D> const& v2)
{
auto result = Vector<std::common_type_t<E1, E2>, D>(v1);
result *= v2;
return result;
}
void TestVector()
{
std::cout << "Testing Vector" << std::endl;
using Vec3 = Vector<float, 3u>;
// Same types. All fine.
{
auto v1 = Vec3({ 1, 2, 3 });
auto v2 = Vec3({ 1, 2, 3 });
v1 *= 2.f;
v1 *= v2;
std::cout << v1 << std::endl;
}
{
auto v1 = Vec3({ 1, 2, 3 });
auto v2 = Vec3({ 1, 2, 3 });
std::cout << (v1 * 2.f) << std::endl;
std::cout << (v1 * v2) << std::endl; // causes problems with std::common_type?
}
{
auto v1 = Vector<float, 3u>({ 1, 2, 3 });
auto v2 = Vector<double, 3u>({ 1, 2, 3 });
v1 *= 2.0; // should probably produce a warning, but doesn't? :(
v1 *= v2; // compiles with warning :)
v2 *= v1; // fine :)
std::cout << v1 << std::endl;
}
{
// The std::common_type versions seem to conflict?
auto v1 = Vector<float, 3u>({ 1, 2, 3 });
auto v2 = v1 * 2.0; // v1 promotion -> should create a Vector<double, 3u>
auto v3 = v1 * v2; // v1 promotion -> should create another Vector<double, 3u>
std::cout << v2 << std::endl;
}
}
所以:
- 我是否需要普通和 std::common_type 运算符版本?
- 使用 std::common_type 的矢量和标量版本似乎会干扰。有可能防止这种情况吗?
- 我该如何完成这项工作?
谢谢。
如果在实现中仅使用相同的操作,则实例化将生成相同的警告。
您可以尝试此示例:
#include <type_traits>
template <typename T>
struct Vect3 {
T a,b,c;
template <typename U, typename V = typename std::common_type<T, U>::type>
Vect3<V> operator*(U u) const { return {a*u,b*u,c*u}; }
template <typename U>
Vect3& operator*=(U u) { a*=u; b*=u; c*=u; return *this; }
};
int main()
{
auto f = Vect3<float>{1,2,3};
auto d = 2.0;
auto common = f * d; // fine!
f *= d; // warns about possible loss of data in the instantion of operator*=
}
即使有-std=c++11 -Wall -pedantic -Wextra -Wconversion -Wconversion-extra
,GCC 也不会发出警告,但对于您的原始示例也没有,所以我猜 GCC 中没有相应的警告
相关文章:
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- 将内置类型变量传递给只有一个类类型参数的"+"运算符函数时自动类型转换的构造函数
- 自定义类型转换运算符在转发引用上调用时不起作用(当对象按值传递时有效)
- 模板化隐式类型转换运算符
- 具有重载类型转换运算符的函数对象崩溃
- 仅为某些模板专用化定义转换运算符:预期类型/预期类型说明符
- 类型转换运算符重载与 as 非成员函数
- 从类模板中排除转换运算符...<类型名 T>基于 T 上的特征
- 初始化中的模板转换运算符类型推导规则是什么?
- C++类型转换运算符
- C++:重载运算符.奇怪的类型转换运算符
- 忽略C++重载类型转换运算符
- 在 Visual Studio 10 中使用类型转换运算符重载时出现 C2440 错误
- 使用了构造函数而不是或类型转换运算符
- 模板类中的类型转换运算符 - 无论显式如何都调用
- 与类型转换运算符一起使用时条件运算符"?:"的编译器错误
- C++类型转换运算符代码,在 Visual Studio 2012 中无法编译,但在 Visual Studio 2005 中工作正常
- 为什么类型转换运算符不适用于继承的类?
- 重载类型转换运算符的语法
- 在 C++ 中定义类型转换运算符模板的正确方法是什么?