Home > Back-end >  Point raw pointer to a shared_ptr
Point raw pointer to a shared_ptr

Time:09-22

I started programming in C after a 1-year break, and I am having difficulties here and there (not that I really knew it before the break).

My current problem is that I don't know how to use pointers properly.

I have the following std::vector:

std::vector<std::shared_ptr<IHittable>> world;

Where IHittable is the interface of Hittable objects.

Now, in this std::vector, multiple derivations of IHittable are pushed, like Sphere, Triangle, etc.

Each of these derived classes has a function intersects() like this:

Intersection Sphere::intersects(const Ray & ray)
{
    auto x = ...
    ...
    return {x, this};
}

Intersection looks like this:

class Intersection
{
    public:
        Intersection(double t, IHittable * object);
        [[nodiscard]] double t() const;
        [[nodiscard]] IHittable * object() const;
    private:
        double t_;
        IHittable * object_ = nullptr;
};

I really don't know how to write this code correctly.

I need to return a this pointer from the member function intersects() of an object which is itself allocated dynamically and is stored in a std::shared_ptr.

Is there a way to handle this?

Another example:

std::vector<std::shared_ptr<IHittable>> world;
world.push_back(std::make_shared<Sphere>());
auto s = Intersection(4.0, world[0]);

Should work.

PS: I could just create multiple std::vectors without std::shared_ptr:

std::vector<Sphere> spheres;
std::vector<Triangles> spheres;
...

But IMHO, it would be nice to iterate over every object at once.

PS2: I am now using shared_from_this() and most of my code works, thanks.

CodePudding user response:

I think this sounds like a good fit for std::enable_shared_from_this as Remy pointed out in the comments.

I whipped up a simplified example which hopefully makes it clear how it can be used to achieve what you're after.

class Intersection;

class IHittable : public std::enable_shared_from_this<IHittable> { 
public:
    virtual Intersection intersects( ) = 0;
    virtual void print( ) const = 0;
    virtual ~IHittable( ) = default;
};

class Intersection {
public:
    Intersection( std::shared_ptr<IHittable> object )
        : object_{ std::move( object ) }
    { }

    void print_shape( ) const {
        object_->print( );
    }
private:
    std::shared_ptr<IHittable> object_;
};

class Square : public IHittable {
public:
    Intersection intersects( ) override {
        return Intersection{ shared_from_this( ) };
    }

    void print( ) const override {
        std::cout << "Square\n";
    }
};

int main( ) {
    std::vector<std::shared_ptr<IHittable>> objects{ 
        std::make_shared<Square>( ) };

    const auto intersect{ objects.front( )->intersects( ) };
    intersect.print_shape( );
}
  • Related