首页 > 解决方案 > 如何使用 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’)

标签: c++

解决方案


如果您希望它起作用(在我看来不应该,但这取决于您),您可以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 r1r2所以类型是由编译器推断出来的。

同样,这取决于您是否认为这种行为对您的班级有意义。


推荐阅读