]> git.tdb.fi Git - libs/math.git/commitdiff
Use unique_ptr for managing memory allocations
authorMikko Rasa <tdb@tdb.fi>
Sun, 26 Jan 2025 00:00:50 +0000 (02:00 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sun, 26 Jan 2025 00:32:23 +0000 (02:32 +0200)
13 files changed:
Build
examples/raytrace.cpp
source/geometry/compositeshape.h
source/geometry/extrudedshape.h
source/geometry/halfspace.h
source/geometry/hyperbox.h
source/geometry/hypersphere.h
source/geometry/intersection.h
source/geometry/loader.h
source/geometry/negation.h
source/geometry/shape.h
source/geometry/transformedshape.h
source/geometry/union.h

diff --git a/Build b/Build
index 2795c66748a663d00e7d6a9933feab925fad2080..c1c5d2e807e8822b78ad1df3de50aad3f53e75fe 100644 (file)
--- a/Build
+++ b/Build
@@ -6,7 +6,7 @@ package "mspmath"
 
        build_info
        {
-               standard CXX "c++11";
+               standard CXX "c++14";
        };
 
        if_arch "linux"
index 7827bd39105674a0d1726b286948257dab9a4880..bed9b1bfcfe085a65306ac308b5f861dd2e9fa91 100644 (file)
@@ -11,7 +11,7 @@ using namespace Msp;
 class RayTracer: public RegisteredApplication<RayTracer>
 {
 private:
-       Geometry::Shape<double, 3> *shape;
+       std::unique_ptr<Geometry::Shape<double, 3>> shape;
        unsigned width;
        unsigned height;
        string filename;
@@ -28,7 +28,6 @@ private:
 
 
 RayTracer::RayTracer(int argc, char **argv):
-       shape(0),
        width(500),
        height(500),
        pixels(new UInt8[width*height])
@@ -42,7 +41,6 @@ RayTracer::RayTracer(int argc, char **argv):
 
 RayTracer::~RayTracer()
 {
-       delete shape;
        delete[] pixels;
 }
 
@@ -89,5 +87,5 @@ void RayTracer::load_shape()
        DataFile::Parser parser(in, filename);
        Geometry::Loader<double, 3> loader;
        loader.load(parser);
-       shape = loader.get_shape().clone();
+       shape = loader.take_shape();
 }
index 012c390f55b8b1afe2aa5bb22d97d64b5b8dbe01..8814ce00cbc576dbeeab5b4602af254d861ff7ee 100644 (file)
@@ -2,6 +2,7 @@
 #define MSP_GEOMETRY_COMPOSITESHAPE_H_
 
 #include <algorithm>
+#include <memory>
 #include <stdexcept>
 #include <vector>
 #include "shape.h"
@@ -17,7 +18,7 @@ class CompositeShape: public Shape<T, D>
 {
 protected:
        typedef O Ops;
-       typedef std::vector<Shape<T, D> *> ShapeArray;
+       typedef std::vector<std::unique_ptr<Shape<T, D>>> ShapeArray;
 
        ShapeArray shapes;
        unsigned max_isect;
@@ -31,9 +32,8 @@ private:
 protected:
        CompositeShape(const CompositeShape &);
        CompositeShape &operator=(const CompositeShape &);
-public:
-       ~CompositeShape() override;
 
+public:
        BoundingBox<T, D> get_axis_aligned_bounding_box(unsigned = 0) const override;
        bool contains(const LinAl::Vector<T, D> &) const override;
        unsigned get_max_ray_intersections() const override { return max_isect; }
@@ -66,39 +66,28 @@ template<typename T, unsigned D, typename O>
 inline void CompositeShape<T, D, O>::init()
 {
        max_isect = 0;
-       for(Shape<T, D> *s: shapes)
+       for(const std::unique_ptr<Shape<T, D>> &s: shapes)
                max_isect += s->get_max_ray_intersections();
 }
 
 template<typename T, unsigned D, typename O>
 inline CompositeShape<T, D, O>::CompositeShape(const CompositeShape<T, D, O> &other):
-       shapes(other.shapes),
        max_isect(other.max_isect)
 {
-       for(Shape<T, D> *&s: shapes)
-               s = s->clone();
+       for(const std::unique_ptr<Shape<T, D>> &s: other.shapes)
+               shapes.push_back(s->clone());
 }
 
 template<typename T, unsigned D, typename O>
 inline CompositeShape<T, D, O> &CompositeShape<T, D, O>::operator=(const CompositeShape<T, D, O> &other)
 {
-       for(Shape<T, D> *s: shapes)
-               delete s;
-
-       shapes = other.shapes;
-       for(Shape<T, D> *&s: shapes)
-               s = s->clone();
+       shapes.clear();
+       for(const std::unique_ptr<Shape<T, D>> &s: shapes)
+               shapes.push_back(s->clone());
 
        max_isect = other.max_isect;
 }
 
-template<typename T, unsigned D, typename O>
-inline CompositeShape<T, D, O>::~CompositeShape()
-{
-       for(Shape<T, D> *s: shapes)
-               delete s;
-}
-
 template<typename T, unsigned D, typename O>
 inline BoundingBox<T, D> CompositeShape<T, D, O>::get_axis_aligned_bounding_box(unsigned detail) const
 {
@@ -120,7 +109,7 @@ template<typename T, unsigned D, typename O>
 inline bool CompositeShape<T, D, O>::contains(const LinAl::Vector<T, D> &point) const
 {
        bool inside = false;
-       for(Shape<T, D> *s: shapes)
+       for(const std::unique_ptr<Shape<T, D>> &s: shapes)
        {
                inside = s->contains(point);
                if(Ops::shortcircuit(inside))
index 027e4f5e61723de2e36b5063e16a59bebe42e0fe..f453a9ce597c88370ada1cac9c076e346877e164 100644 (file)
@@ -17,16 +17,15 @@ template<typename T, unsigned D>
 class ExtrudedShape: public Shape<T, D>
 {
 private:
-       Shape<T, D-1> *base = nullptr;
+       std::unique_ptr<Shape<T, D-1>> base;
        T length = T(1);
 
 public:
        ExtrudedShape(const Shape<T, D-1> &, T);
        ExtrudedShape(const ExtrudedShape &);
        ExtrudedShape &operator=(const ExtrudedShape &);
-       ~ExtrudedShape() override;
 
-       ExtrudedShape *clone() const override;
+       std::unique_ptr<Shape<T, D>> clone() const override;
 
        const Shape<T, D-1> &get_base() const { return *base; }
        T get_length() const { return length; }
@@ -57,21 +56,14 @@ inline ExtrudedShape<T, D>::ExtrudedShape(const ExtrudedShape<T, D> &other):
 template<typename T, unsigned D>
 inline ExtrudedShape<T, D> &ExtrudedShape<T, D>::operator=(const ExtrudedShape<T, D> &other)
 {
-       delete base;
        base = other.base->clone();
        length = other.length;
 }
 
 template<typename T, unsigned D>
-inline ExtrudedShape<T, D>::~ExtrudedShape()
+inline std::unique_ptr<Shape<T, D>> ExtrudedShape<T, D>::clone() const
 {
-       delete base;
-}
-
-template<typename T, unsigned D>
-inline ExtrudedShape<T, D> *ExtrudedShape<T, D>::clone() const
-{
-       return new ExtrudedShape<T, D>(*base, length);
+       return std::make_unique<ExtrudedShape<T, D>>(*base, length);
 }
 
 template<typename T, unsigned D>
index 5271bd683fba434c3c7b7f3ffe57867d730f59d0..87531984ee7875133d407db43aba15c3ba4b5a91 100644 (file)
@@ -20,7 +20,7 @@ public:
        HalfSpace();
        HalfSpace(const LinAl::Vector<T, D> &);
 
-       HalfSpace *clone() const override;
+       std::unique_ptr<Shape<T, D>> clone() const override;
 
        const LinAl::Vector<T, D> &get_normal() const { return normal; }
 
@@ -43,9 +43,9 @@ inline HalfSpace<T, D>::HalfSpace(const LinAl::Vector<T, D> &n):
 { }
 
 template<typename T, unsigned D>
-inline HalfSpace<T, D> *HalfSpace<T, D>::clone() const
+inline std::unique_ptr<Shape<T, D>> HalfSpace<T, D>::clone() const
 {
-       return new HalfSpace<T, D>(normal);
+       return std::make_unique<HalfSpace<T, D>>(normal);
 }
 
 template<typename T, unsigned D>
index 1743251c5e6e445a791017cea52cb601dc8788ab..cb7a661812c9e25bb32f1369320b79eccbdab3eb 100644 (file)
@@ -24,7 +24,7 @@ public:
        HyperBox();
        explicit HyperBox(const LinAl::Vector<T, D> &);
 
-       HyperBox *clone() const override;
+       std::unique_ptr<Shape<T, D>> clone() const override;
 
        const LinAl::Vector<T, D> &get_dimensions() const { return dimensions; }
        T get_dimension(unsigned) const;
@@ -53,9 +53,9 @@ inline HyperBox<T, D>::HyperBox(const LinAl::Vector<T, D> &d):
 }
 
 template<typename T, unsigned D>
-inline HyperBox<T, D> *HyperBox<T, D>::clone() const
+inline std::unique_ptr<Shape<T, D>> HyperBox<T, D>::clone() const
 {
-       return new HyperBox<T, D>(dimensions);
+       return std::make_unique<HyperBox<T, D>>(dimensions);
 }
 
 template<typename T, unsigned D>
index 94ccae9b83c7eb767e74140c65ac4ab50beba7c3..368549bb415d5f8f51ee2c9476c839770dacdf95 100644 (file)
@@ -23,7 +23,7 @@ public:
        HyperSphere() = default;
        explicit HyperSphere(T);
 
-       HyperSphere *clone() const override;
+       std::unique_ptr<Shape<T, D>> clone() const override;
 
        T get_radius() const { return radius; }
 
@@ -43,9 +43,9 @@ inline HyperSphere<T, D>::HyperSphere(T r):
 }
 
 template<typename T, unsigned D>
-inline HyperSphere<T, D> *HyperSphere<T, D>::clone() const
+inline std::unique_ptr<Shape<T, D>> HyperSphere<T, D>::clone() const
 {
-       return new HyperSphere<T, D>(radius);
+       return std::make_unique<HyperSphere<T, D>>(radius);
 }
 
 template<typename T, unsigned D>
index 6ea0602ff336a516206a645b42fee14b84608705..cdf41e91145a2fe217ac9e773e4e6119bd8d26d0 100644 (file)
@@ -28,7 +28,7 @@ public:
        template<typename Iter>
        static Intersection from_iterator_range(const Iter &, const Iter &);
 
-       Intersection *clone() const override;
+       std::unique_ptr<Shape<T, D>> clone() const override;
 };
 
 template<typename T, unsigned D>
@@ -46,9 +46,9 @@ inline Intersection<T, D> Intersection<T, D>::from_iterator_range(const Iter &be
 }
 
 template<typename T, unsigned D>
-inline Intersection<T, D> *Intersection<T, D>::clone() const
+inline std::unique_ptr<Shape<T, D>> Intersection<T, D>::clone() const
 {
-       return new Intersection<T, D>(*this);
+       return std::make_unique<Intersection<T, D>>(*this);
 }
 
 } // namespace Geometry
index 6b03bbb4826dc8de9a5ffc3bfa2086a9c493a50f..c3774b74f88b4b0a81d8dab3c0f82efe75811bbb 100644 (file)
@@ -21,13 +21,12 @@ class DimensionIndependentLoader: public DataFile::Loader
 {
 protected:
        bool single = true;
-       std::list<Shape<T, D> *> shapes;
+       std::list<std::unique_ptr<Shape<T, D>>> shapes;
 
        DimensionIndependentLoader(bool = true);
-public:
-       ~DimensionIndependentLoader() override;
 
-       const Shape<T, D> &get_shape() const;
+public:
+       std::unique_ptr<Shape<T, D>> take_shape();
 
 protected:
        template<typename S>
@@ -65,7 +64,7 @@ private:
 public:
        ShapeLoader();
 
-       ExtrudedShape<T, D> *create() const;
+       std::unique_ptr<ExtrudedShape<T, D>> create() const;
 
 private:
        void length(T);
@@ -80,7 +79,7 @@ private:
 public:
        ShapeLoader();
 
-       HalfSpace<T, D> *create() const;
+       std::unique_ptr<Shape<T, D>> create() const;
 
 private:
        void normal(const std::vector<T> &);
@@ -95,7 +94,7 @@ private:
 public:
        ShapeLoader();
 
-       HyperBox<T, D> *create() const;
+       std::unique_ptr<Shape<T, D>> create() const;
 
 private:
        void dimensions(const std::vector<T> &);
@@ -110,7 +109,7 @@ private:
 public:
        ShapeLoader();
 
-       HyperSphere<T, D> *create() const;
+       std::unique_ptr<Shape<T, D>> create() const;
 
 private:
        void radius(T);
@@ -122,7 +121,7 @@ class CompositeLoader: public Loader<T, D>
 public:
        CompositeLoader();
 
-       S *create() const;
+       std::unique_ptr<Shape<T, D>> create() const;
 };
 
 template<typename T, unsigned D>
@@ -133,7 +132,7 @@ template<typename T, unsigned D>
 class ShapeLoader<Negation<T, D> >: public Loader<T, D>
 {
 public:
-       Negation<T, D> *create() const;
+       std::unique_ptr<Shape<T, D>> create() const;
 };
 
 template<typename T, unsigned D>
@@ -145,7 +144,7 @@ protected:
 public:
        TransformationLoader();
 
-       TransformedShape<T, D> *create() const;
+       std::unique_ptr<Shape<T, D>> create() const;
 
        void translate(const std::vector<T> &);
        void scale(const std::vector<T> &);
@@ -193,18 +192,11 @@ inline DimensionIndependentLoader<T, D>::DimensionIndependentLoader(bool s):
 }
 
 template<typename T, unsigned D>
-inline DimensionIndependentLoader<T, D>::~DimensionIndependentLoader()
-{
-       for(Shape<T, D> *s: shapes)
-               delete s;
-}
-
-template<typename T, unsigned D>
-inline const Shape<T, D> &DimensionIndependentLoader<T, D>::get_shape() const
+inline std::unique_ptr<Shape<T, D>> DimensionIndependentLoader<T, D>::take_shape()
 {
        if(shapes.empty())
                throw std::runtime_error("no shape");
-       return *shapes.front();
+       return std::move(shapes.front());
 }
 
 template<typename T, unsigned D>
@@ -241,9 +233,9 @@ inline ShapeLoader<ExtrudedShape<T, D> >::ShapeLoader():
 }
 
 template<typename T, unsigned D>
-inline ExtrudedShape<T, D> *ShapeLoader<ExtrudedShape<T, D> >::create() const
+inline std::unique_ptr<ExtrudedShape<T, D>> ShapeLoader<ExtrudedShape<T, D> >::create() const
 {
-       return new ExtrudedShape<T, D>(*this->shapes.front(), length_);
+       return std::make_unique<ExtrudedShape<T, D>>(*this->shapes.front(), length_);
 }
 
 template<typename T, unsigned D>
@@ -262,9 +254,9 @@ inline ShapeLoader<HalfSpace<T, D> >::ShapeLoader()
 }
 
 template<typename T, unsigned D>
-inline HalfSpace<T, D> *ShapeLoader<HalfSpace<T, D> >::create() const
+inline std::unique_ptr<Shape<T, D>> ShapeLoader<HalfSpace<T, D> >::create() const
 {
-       return new HalfSpace<T, D>(normal_);
+       return std::make_unique<HalfSpace<T, D>>(normal_);
 }
 
 template<typename T, unsigned D>
@@ -287,9 +279,9 @@ inline ShapeLoader<HyperBox<T, D> >::ShapeLoader()
 }
 
 template<typename T, unsigned D>
-inline HyperBox<T, D> *ShapeLoader<HyperBox<T, D> >::create() const
+inline std::unique_ptr<Shape<T, D>> ShapeLoader<HyperBox<T, D> >::create() const
 {
-       return new HyperBox<T, D>(dimensions_);
+       return std::make_unique<HyperBox<T, D>>(dimensions_);
 }
 
 template<typename T, unsigned D>
@@ -310,9 +302,9 @@ inline ShapeLoader<HyperSphere<T, D> >::ShapeLoader():
 }
 
 template<typename T, unsigned D>
-inline HyperSphere<T, D> *ShapeLoader<HyperSphere<T, D> >::create() const
+inline std::unique_ptr<Shape<T, D>> ShapeLoader<HyperSphere<T, D> >::create() const
 {
-       return new HyperSphere<T, D>(radius_);
+       return std::make_unique<HyperSphere<T, D>>(radius_);
 }
 
 template<typename T, unsigned D>
@@ -323,9 +315,9 @@ inline void ShapeLoader<HyperSphere<T, D> >::radius(T r)
 
 
 template<typename T, unsigned D>
-inline Negation<T, D> *ShapeLoader<Negation<T, D> >::create() const
+inline std::unique_ptr<Shape<T, D>> ShapeLoader<Negation<T, D> >::create() const
 {
-       return new Negation<T, D>(*this->shapes.front());
+       return std::make_unique<Negation<T, D>>(*this->shapes.front());
 }
 
 
@@ -338,9 +330,9 @@ inline TransformationLoader<T, D>::TransformationLoader()
 }
 
 template<typename T, unsigned D>
-inline TransformedShape<T, D> *TransformationLoader<T, D>::create() const
+inline std::unique_ptr<Shape<T, D>> TransformationLoader<T, D>::create() const
 {
-       return new TransformedShape<T, D>(*this->shapes.front(), transformation);
+       return std::make_unique<TransformedShape<T, D>>(*this->shapes.front(), transformation);
 }
 
 template<typename T, unsigned D>
@@ -411,7 +403,7 @@ inline CompositeLoader<T, D, S>::CompositeLoader():
 { }
 
 template<typename T, unsigned D, typename S>
-inline S *CompositeLoader<T, D, S>::create() const
+inline std::unique_ptr<Shape<T, D>> CompositeLoader<T, D, S>::create() const
 {
        if(this->shapes.empty())
                throw std::runtime_error("no shapes");
index 4947bbf4415f346c0423165c56de3accc724ed4e..9c781e9a8ab98279c734a755e90bd0dc83f9232e 100644 (file)
@@ -14,15 +14,14 @@ template<typename T, unsigned D>
 class Negation: public Shape<T, D>
 {
 private:
-       Shape<T, D> *shape = nullptr;
+       std::unique_ptr<Shape<T, D>> shape;
 
 public:
        Negation(const Shape<T, D> &);
        Negation(const Negation &);
        Negation &operator=(const Negation &);
-       ~Negation();
 
-       Negation *clone() const override;
+       std::unique_ptr<Shape<T, D>> clone() const override;
 
        const Shape<T, D> &get_shape() const { return *shape; }
 
@@ -46,21 +45,14 @@ inline Negation<T, D>::Negation(const Negation<T, D> &other):
 template<typename T, unsigned D>
 inline Negation<T, D> &Negation<T, D>::operator=(const Negation<T, D> &other)
 {
-       delete shape;
        shape = other.shape->clone();
        return *this;
 }
 
 template<typename T, unsigned D>
-inline Negation<T, D>::~Negation()
+inline std::unique_ptr<Shape<T, D>> Negation<T, D>::clone() const
 {
-       delete shape;
-}
-
-template<typename T, unsigned D>
-inline Negation<T, D> *Negation<T, D>::clone() const
-{
-       return new Negation<T, D>(*shape);
+       return std::make_unique<Negation<T, D>>(*shape);
 }
 
 template<typename T, unsigned D>
index 543550dbc0616db13a20f35a49f5cf817cf7cbf4..bd90ba62eca800f6a69f7b5b5802e5f82e36049b 100644 (file)
@@ -2,6 +2,7 @@
 #define MSP_GEOMETRY_SHAPE_H_
 
 #include <list>
+#include <memory>
 #include <vector>
 #include <msp/linal/vector.h>
 #include "boundingbox.h"
@@ -39,7 +40,7 @@ protected:
 public:
        virtual ~Shape() = default;
 
-       virtual Shape *clone() const = 0;
+       virtual std::unique_ptr<Shape> clone() const = 0;
 
        /** Returns the bounding box of the shape.  The detail parameter controls
        the tightness of the box.  Higher detail will take more time to compute. */
index 1cab02266672cfdce60049df0e86f067b427dd8d..7ea7268cf5cbb629f57c424141a1381fdb2d2d6b 100644 (file)
@@ -14,7 +14,7 @@ template<typename T, unsigned D>
 class TransformedShape: public Shape<T, D>
 {
 private:
-       Shape<T, D> *shape = nullptr;
+       std::unique_ptr<Shape<T, D>> shape;
        AffineTransform<T, D> transformation;
        AffineTransform<T, D> inverse_trans;
 
@@ -22,9 +22,8 @@ public:
        TransformedShape(const Shape<T, D> &, const AffineTransform<T, D> &);
        TransformedShape(const TransformedShape &);
        TransformedShape &operator=(const TransformedShape &);
-       ~TransformedShape();
 
-       TransformedShape *clone() const override;
+       std::unique_ptr<Shape<T, D>> clone() const override;
 
        const Shape<T, D> &get_shape() const { return *shape; }
        const AffineTransform<T, D> &get_transformation() const { return transformation; }
@@ -53,22 +52,15 @@ inline TransformedShape<T, D>::TransformedShape(const TransformedShape<T, D> &ot
 template<typename T, unsigned D>
 inline TransformedShape<T, D> &TransformedShape<T, D>::operator=(const TransformedShape<T, D> &other)
 {
-       delete shape;
        shape = other.shape->clone();
        transformation = other.transformation;
        inverse_trans = other.inverse_trans;
 }
 
 template<typename T, unsigned D>
-inline TransformedShape<T, D>::~TransformedShape()
+inline std::unique_ptr<Shape<T, D>> TransformedShape<T, D>::clone() const
 {
-       delete shape;
-}
-
-template<typename T, unsigned D>
-inline TransformedShape<T, D> *TransformedShape<T, D>::clone() const
-{
-       return new TransformedShape<T, D>(*this);
+       return std::make_unique<TransformedShape<T, D>>(*this);
 }
 
 template<typename T, unsigned D>
index 7d77ed18033dc84ee0dca5acbd5bc7008cc0ca53..e25c750f469d5e7d3aa1d711ef6d20751a6c3ca8 100644 (file)
@@ -28,7 +28,7 @@ public:
        template<typename Iter>
        static Union from_iterator_range(const Iter &, const Iter &);
 
-       Union *clone() const override;
+       std::unique_ptr<Shape<T, D>> clone() const override;
 };
 
 template<typename T, unsigned D>
@@ -46,9 +46,9 @@ inline Union<T, D> Union<T, D>::from_iterator_range(const Iter &begin, const Ite
 }
 
 template<typename T, unsigned D>
-inline Union<T, D> *Union<T, D>::clone() const
+inline std::unique_ptr<Shape<T, D>> Union<T, D>::clone() const
 {
-       return new Union<T, D>(*this);
+       return std::make_unique<Union<T, D>>(*this);
 }
 
 } // namespace Geometry