[英]Infer the (templated) return type of operator+ and other operators
我正在實現一個二維向量,它的坐標可以采用任何算術類型。 我想實現一個operator+
運算符,它以與unsigned x = 2l + 3.1;
相同的方式從上下文推斷其返回類型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
找出它的最簡單方法。
所以,加入Vec2
的int
s到一個Vec2
的double
S的關系產生Vec2<double>
。 但是如果這被分配給Vec2<int>
呢? 好吧,您只需要一個轉換運算符...
template<typename TB>
operator Vec2<TB>() const
{
return Vec2<TB>(_data[0], _data[1]);
}
......並希望最好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.