c++ - 推断 operator+ 和其他运算符的(模板化)返回类型
问题描述
我正在实现一个二维向量,它可以采用任何算术类型作为其坐标。我想实现一个operator+
运算符,它从上下文推断其返回类型,就像unsigned x = 2l + 3.1;
知道+
应该的结果一样,unsigned
因为它被分配给unsigned
.
到目前为止,我的灵感来自于从返回类型推断类型 T 的模板:
#include <array>
#include <type_traits>
template<typename T,
typename = std::enable_if_t<std::is_arithmetic_v<T>, T>>
class Vec2
{
std::array<T, 2> _data;
public:
// Constructors
Vec2(T x, T y): _data{x, y} {}
// Operators
template<typename TB, // second operand's coordinates type
typename TR> // result's coordinates type
Vec2<TR> operator+(const Vec2<TB> v) const
{
return Vec2<TR>(_data[0] + v._data[0],
_data[1] + v._data[1]);
}
};
int main(void)
{
Vec2 vi{0, 2};
Vec2 vf{1.4, 2.2};
Vec2<int> res = vi + vf;
}
我收到一条错误消息,说它无法推断出用于返回值的类型:
$ g++ -Wall -Wextra -std=c++17 poc.cc
poc.cc: In function ‘int main()’:
poc.cc:29:24: error: no match for ‘operator+’ (operand types are ‘Vec2<int, int>’ and ‘Vec2<double, double>’)
29 | Vec2<int> res = vi + vf;
| ~~ ^ ~~
| | |
| | Vec2<double,double>
| Vec2<int,int>
poc.cc:17:14: note: candidate: ‘template<class TB, class TR> Vec2<TR> Vec2<T, <template-parameter-1-2> >::operator+(Vec2<TB>) const [with TB = TB; TR = TR; T = int; <template-parameter-1-2> = int]’
17 | Vec2<TR> operator+(const Vec2<TB> v) const
| ^~~~~~~~
poc.cc:17:14: note: template argument deduction/substitution failed:
poc.cc:29:26: note: couldn’t deduce template parameter ‘TR’
29 | Vec2<int> res = vi + vf;
| ^~
poc.cc:29:15: warning: unused variable ‘res’ [-Wunused-variable]
29 | Vec2<int> res = vi + vf;
| ^~~
解决方案
在 C++ 中,+
运算符重载无法确定其结果将分配给什么。C++ 根本无法以这种方式工作。
在许多情况下,可以以稍微不同的方式设计一种替代方法。首先让+
操作员弄清楚它的最佳返回类型应该是什么:
template<typename TB> // result's coordinates type
auto operator+(const Vec2<TB> v) const
{
typedef decltype( static_cast<T>(0) + static_cast<TB>(0) ) ret_t;
return Vec2<ret_t>(_data[0] + v._data[0],
_data[1] + v._data[1]);
}
您要确保T
和TB
都是算术类型,因此这是通过decltype
.
因此,将 a Vec2
of int
s 添加到 a Vec2
of double
s 应该产生 a Vec2<double>
。但是,如果这被分配给 aVec2<int>
怎么办?好吧,您只需要一个转换运算符...
template<typename TB>
operator Vec2<TB>() const
{
return Vec2<TB>(_data[0], _data[1]);
}
......并希望最好。
推荐阅读
- python - 函数 range(len(sequence)-1,0,-1) 中的数字是什么意思?
- java - 如何创建获取服务以从 JIRA 检索 sprint 报告?有人可以帮我完成图片中的第二步吗?
- apache-spark - 无法使用 XgBoost 训练模型 - PySpark
- python - 无法使用请求从网页中获取所有表格内容
- vue.js - 如何在列表上设置 Vuetify 分页
- asp.net-core - 如何在 Asp.Net Core 的 JsonResult 中返回错误状态?
- r - 使用自动绘图功能增加轴刻度的数量(时间序列数据)
- python - Beautifulsoup 为文本和链接解析 html 表
- spring - 是否可以将 spring.cloud.config 配置为使用多个 bootstrap.yml 文件
- python - OSX 中的 wxPython 4.0.6 - 单击菜单栏图标不会触发事件