c++ - 如何使用 common_type 和模板递归类型重载 operator+
问题描述
我不确定如何描述模板的类型何时是结构本身,如下所示。
template<typename T> struct Point{};
Point<Point<int>> p;
这是定义的行为吗?如果是这样,我不知道实现它的最佳方法,以便我可以返回一个 common_type 而不会出现错误,如下所示。
#include <iostream>
template<typename T> struct Point
{
Point() {}
template<typename U, typename V> Point(const U& u, const V& v): x(u), y(v) {}
T x,y;
};
template<typename T, typename U>
inline Point<typename std::common_type<T, U>::type> operator+(const Point<T>& p, const U& n)
{
return {p.x+n, p.y+n};
}
int main() {
Point<int> p;
Point<double> r1 = p + 1.5; //works
Point<Point<int>> p2;
Point<Point<double>> r2 = p2 + 1.5; //error
return 0;
}
错误是:
no match for ‘operator+’ (operand types are ‘Point<Point<int> >’ and ‘double’)
解决方案
如果您希望它起作用(在我看来不应该,但这取决于您),您可以decltype(std::declval<T>()+std::declval<U>())
使用std::common_type<...>
.
#include <iostream>
template<typename T> struct Point
{
Point(): x{}, y{} {}
template<typename U, typename V> Point(const U& u, const V& v): x(u), y(v) {}
T x,y;
};
template<typename T, typename U>
inline Point<decltype(std::declval<T>()+std::declval<U>())> operator+(const Point<T>& p, const U& n)
{
return {p.x+n, p.y+n};
}
template<typename T>
std::ostream &operator<<(std::ostream& os, const Point<T>& p)
{
os << "Point<" << typeid(T).name() << ">(x=" << p.x << ", y=" << p.y << ")";
return os;
}
int main() {
Point<int> p;
auto r1 = p + 1.5;
Point<Point<int>> p2;
auto r2 = p2 + 1.5;
std::cout << p << "\n";
std::cout << r1 << "\n";
std::cout << p2 << "\n";
std::cout << r2 << "\n";
return 0;
}
我还添加了一个超载打印出一个点。由于 C++ 标准不能保证typeid(T).name()
您可能会看到不同的东西,但这就是我得到的:
Point<i>(x=0, y=0)
Point<d>(x=1.5, y=1.5)
Point<5PointIiE>(x=Point<i>(x=0, y=0), y=Point<i>(x=0, y=0))
Point<5PointIdE>(x=Point<d>(x=1.5, y=1.5), y=Point<d>(x=1.5, y=1.5))
Point<i>
是Point<int>
,Point<d>
是Point<double>
,Point<5PointIiE>
是,是Point<Point<int>>
,Point<5PointIdE>
是Point<Point<double>>
。请注意,我使用auto
了 for r1
,r2
所以类型是由编译器推断出来的。
同样,这取决于您是否认为这种行为对您的班级有意义。
推荐阅读
- javascript - 提交后谷歌脚本网络应用程序进入空白页面
- python - 如何正确进行xpath“和”/条件查询?
- javascript - 使用类型默认值将 GraphQL 查询转换为 JS 对象
- android - 错误:[kapt] java.lang.IllegalArgumentException:@androidx.room.ColumnInfo 未定义元素 defaultValue()
- angular - 将 Ionic 从 3 更新到 4 后无法访问 PouchDB 数据(带有适配器 WebSQL)
- git - bitbucket git push 错误:pack-objects 死于信号 127
- python - 如何模拟一个zip文件
- javascript - 为什么 Chrome 审核在本地开发中没有显示错误,但在部署时显示 3 个错误
- python - 在Python中初始化构造函数之外的继承类
- scrollview - Slickgrid:范围选择上的滚动网格