自动符号转换,用于对类等数学向量进行操作
Automatic sign conversion for operations on math-vector like class
我有一个自定义向量(用于数学上下文而不是std::vector
(,它在元素类型上模板化。 它还提供从其他类型的显式转换。
总之:
template <typename T>
struct Point
{
T x, y;
Point(const T x, const T y): x(x), y(y) {}
Point(const Point& other): x(other.x), y(other.y){}
template<typename U>
explicit Point(const Point<U>& pt): x(static_cast<T>(pt.x)), y(static_cast<T>(pt.y)) {}
Point& operator+=(const Point& right);
friend Point operator+(Point left, const Point& right) { return (left+=right); }
};
现在我使用带有符号类型的 typedefs 作为职位,使用无符号类型表示大小。但是我发现我需要经常将它们结合起来,这在转换中变得很麻烦。看:
typedef Point<int> Pos;
typedef Point<unsigned> Extent;
Pos pos = ...;
Extent size = ...;
std::cout << "The outside is: " << (pos + Pos(size));
我想要的是无符号类型会自动转换为有符号类型,而不是相反,所以我可以简单地编写pos + size
.
这容易吗?
推理说明:我可以组合有符号和无符号的基本类型,如5 + 6u
,从而产生
更好的是,如果自动转换仅在使用数学运算符时才适用。
编辑:仅限C++98,但允许提升
您可以将operator+
编写为 free 函数,该函数用作返回类型"添加两种类型的结果类型",例如:
template <typename T>
Point<T> make_point(T x, T y)
{
return Point<T>(x, y);
}
template <typename T, typename U>
auto operator+(Point<T> const & lhs, Point<U> const & rhs)
// -> decltype(make_point(lhs.x + rhs.x, lhs.y + rhs.y))
{
return make_point(lhs.x + rhs.x, lhs.y + rhs.y);
}
其中make_point
只是为我们做一些类型推断,operator+
auto
返回类型也为我们做类型推断(您可以使用decltype
和std::declval
-构造"手动"完成(。您至少需要一个 c++14 编译器才能正常工作(如果您取消注释尾随返回类型,则为 c++11(。当然,您可以将类似的代码用于operator-
、operator*
等。
您需要声明重载operator+
,以允许它接受具有不同类型参数Point<>
类。
其次,您可以依靠std::common_type
在两者之间选择正确的结果类型。 即避免缩小转换的常见算术类型:
template <typename T>
struct Point
{
// as before, including your original operator+
template<typename S, typename U,
typename std::enable_if<!std::is_same<S, U>::value>::type* = nullptr,
typename ResType = typename std::common_type<S, U>::type>
friend Point<ResType> operator+(const Point<S>& left, const Point<U>& right) {
return Point<ResType>{left} + Point<ResType>{right};
}
};
中间略微复杂的enable_if
是一种SFINAE技术,用于避免S
和U
相同时的GCC重定义错误。
在@MadScientiest和@StoryTeller的答案的基础上,我使用了以下内容:
首先是一个特征来获得结果类型
template<typename T>
struct TryMakeSigned
{
typedef typename boost::conditional<
boost::is_integral<T>::value,
boost::make_signed<T>,
boost::common_type<T>
>::type::type type;
};
/// Creates a mixed type out of types T and U which is
/// the common type of T & U AND signed iff either is signed
/// fails for non-numeric types with SFINAE
template<typename T, typename U, bool T_areNumeric = boost::is_arithmetic<T>::value && boost::is_arithmetic<U>::value>
struct MixedType;
template<typename T, typename U>
struct MixedType<T, U, true>
{
typedef typename boost::common_type<T, U>::type Common;
// Convert to signed iff least one value is signed
typedef typename boost::conditional<
boost::is_signed<T>::value || boost::is_signed<U>::value,
typename TryMakeSigned<Common>::type,
Common
>::type type;
};
第二次用于非成员运营商:
template <typename T, typename U>
inline Point<typename detail::MixedType<T, U>::type> operator+(const Point<T>& lhs, const Point<U>& rhs)
{
typedef typename detail::MixedType<T, U>::type Res;
return Point<Res>(lhs.x + rhs.x, lhs.y + rhs.y);
}
但是,这不考虑隐式转换。让那些将函数声明为类中的友元函数(省略typename T
- 为什么一个向量上的多线程操作很慢
- C++ 随机数生成器:尝试将结果作为向量获取,但通过制作 void 函数来执行此操作而出现错误
- 为什么我必须在作案操作中解析向量的大小?
- 如何有效地操作满足给定谓词的向量中的所有项目?
- 通过浮点指针操作字节向量
- 自动符号转换,用于对类等数学向量进行操作
- 防止在不同尺寸的,模板,多态性的数学向量上进行组件操作
- 合并排序的合并操作无法使用 c++ 向量
- 向量操作
- 如何在C 对向量的第二个元素上执行较低的操作
- 向量元素数据损坏了Find()操作
- STD ::向量迭代器类型和允许的操作
- 将std ::向量复制到CV :: Mat_的行操作相同
- 如何在C 向量操作中修复误差
- 调用向量内的函数指针不执行任何操作
- 如果矩阵密集且不对称,特征库矩阵/矢量操作是否比 .net 矩阵/向量操作更快?
- 如何在LLVM位向量上操作?
- 对象在将操作推送到向量后成员变量值已更改
- 非逻辑代码流 /无效的向量操作
- C++结构上的 Stl 向量操作