有没有办法编写处理智能指针和常规指针的模板函数?

is there a way to write a template function for dealing with smart pointer and regular pointer?

我正在尝试编写一个接受智能指针或常规指针向量的函数,但它永远无法工作,我想编写函数 getLargestRadius() 接受作为参数 std::vector<something*>std::vector<std::shared_ptr<something>>。 它对我有用的唯一方法是重载函数 这是我的完整代码,可以准确理解我的意思:

#include <iostream>
#include <vector>
#include <memory>

class Point
{
private:
    int m_x{ 0 };
    int m_y{ 0 };
    int m_z{ 0 };

public:
    Point() = default;
    Point(int x, int y, int z)
        : m_x{x}, m_y{y}, m_z{z}
    {

    }

    friend std::ostream& operator<<(std::ostream &out, const Point &p)
    {
        out << "Point(" << p.m_x << ", " << p.m_y << ", " << p.m_z << ')';
        return out;
    }
};

class Shape
{
public:
    virtual std::ostream& print(std::ostream &out) const = 0;

    friend std::ostream& operator <<(std::ostream &out, const Shape &shape)
    {
        return shape.print(out);
    }
    virtual ~Shape() {}
};

class Triangle : public Shape
{
private:
    Point m_a;
    Point m_b;
    Point m_c;
public:
    Triangle(const Point &a, const Point &b, const Point &c)
        : m_a{a}, m_b{b}, m_c{c}
    {}
    virtual std::ostream& print(std::ostream &out) const override
    {
        out << "Trinagle(";
        out << m_a << ", ";
        out << m_b << ", ";
        out << m_c << ")";
        return out;
    }

};
class Circle: public Shape
{
private:
    Point m_center;
    int m_radius;

public:
    Circle(const Point &center, int radius)
        : m_center{center}, m_radius{radius}
    {
    }

    virtual std::ostream& print(std::ostream &out) const override
    {
        out << "Circle(" << m_center << ", radius " << m_radius << ')';
        return out;
    }

    int getRadius() const {return m_radius;}
};


int getLargestRadius(std::vector<std::shared_ptr<Shape>> &v)
{
    int largestRadius { 0 };

    for(int x{0}; x < static_cast<int>(v.size()); ++x)
    {
            if (dynamic_pointer_cast<Circle>(v[x]))
        {
            if (dynamic_cast<Circle&>(*v[x]).getRadius() > largestRadius)
                largestRadius = dynamic_cast<Circle&>(*v[x]).getRadius();
        }
    }

    return largestRadius;
}

int getLargestRadius(std::vector<Shape*> &v)
{
    int largestRadius { 0 };

    for(int x{0}; x < static_cast<int>(v.size()); ++x)
    {
            if (dynamic_cast<Circle*>(v[x]))
        {
            if (dynamic_cast<Circle*>(v[x])->getRadius() > largestRadius)
                largestRadius = dynamic_cast<Circle*>(v[x])->getRadius();
        }
    }

    return largestRadius;
}
int main()
{

    std::vector<std::shared_ptr<Shape>> v1 {
        std::make_shared<Circle>(Point{1, 2, 3}, 7),
        std::make_shared<Triangle>(Point{1, 2, 3}, Point{4, 5, 6}, Point{7, 8, 9}),
        std::make_shared<Circle>(Point{4, 5, 6}, 3)
    };

    std::vector<Shape*> v2{
      new Circle{Point{1, 2, 3}, 7},
      new Triangle{Point{1, 2, 3}, Point{4, 5, 6}, Point{7, 8, 9}},
      new Circle{Point{4, 5, 6}, 3}
    };

    for(auto &element : v1)
        std::cout << *element << '\n';


    std::cout << "The largest radius is: " << getLargestRadius(v1) << '\n';
    std::cout << "The largest radius is: " << getLargestRadius(v2) << '\n';

    for(auto &element : v2)
        delete element;

    return 0;
}

我试图将其作为模板,但没有任何效果。 如您所见,我必须重载该函数才能使其与两种矢量类型一起使用 那么有没有一种方法可以使用模板使其只有一个函数适用于所有类型。

谢谢

不用检查,你可以用 template:

template <typename T>
int getLargestRadius(const std::vector<T>& v)
{
    int largestRadius { 0 };

    for (const auto& shapePtr : v)
    {
        if (const auto* circle = dynamic_cast<const Circle*>(&*shapePtr))
        {
            largestRadius = std::max(largestRadius , circle->radius);
        }
    }

    return largestRadius;
}

为了平等对待常规指针和智能指针,我尊重它们 (*shapePtr) 所以我有一个参考。

(然后我需要取回常规指针,所以我取地址&*shapePtr)。