1ups_
1ups_

Reputation: 47

templated class segfaults when using inheritance

I am currently working on a raytracer, and I am trying to output the result using multiple ways at the same time (only through PPM format and using SFML atm). To achieve that, I wrote an IOutput interface that gets inherited by the classes corresponding to each way of rendering an image.

Here is the problematic piece of code:

#ifndef PPM_FILE_HPP_
#define PPM_FILE_HPP_

// #include "../Core/math.hpp"

#include <tuple>
#include <array>

#include <string>
#include <fstream>
#include <sstream>

namespace Math {

    class Vector3D {
    public:
        double x, y, z;

        Vector3D() : x(0), y(0), z(0) {}

        Vector3D(double _x, double _y, double _z) : x(_x), y(_y), z(_z) {}
    };
}

template <int width, int height>
class IOutput {
    public:
        IOutput() : is_rendered(false) {}
        virtual void refresh() = 0;
        virtual void set_pixel(std::tuple<int, int> location, Math::Vector3D color) = 0;
        virtual void set_as_rendered() = 0;

    protected:
        std::array<std::array<Math::Vector3D, width>, height> grid;
        bool is_rendered = false;
};

template <int width, int height>
class PPM_file : public IOutput<width, height> {
    public:
        PPM_file(std::string filename) : IOutput<width, height>(), file(filename), color_depth(255)
        {
            if (!file.is_open())
                throw std::runtime_error("Unable to open file: " + filename);
            file << "P3\n" << width << " " << height << "\n" << color_depth << "\n";
        }
        ~PPM_file()
        {
            if (!this->is_rendered)
                set_as_rendered();
            if (file.is_open())
                file.close();
        }
        void refresh() override {};
        void set_pixel(std::tuple<int, int> location, Math::Vector3D color) override
        {
            int x = std::get<0>(location);
            int y = std::get<1>(location);

            if (x >= 0 && x < width && y >= 0 && y < height) {
                this->grid[y][x] = color;
            } else {
                std::cerr << "Error: Pixel location (" << x << ", " << y << ") is out of bounds." << std::endl;
            }
        }
        void set_as_rendered() override
        {
            this->is_rendered = true;
            for (const auto& row : this->grid) {
                for (const auto& pixel : row) {
                    file << vec3_to_string(pixel);
                }
            }
            file.close();
        }

    protected:
        std::ofstream file;
        int color_depth;
    private:
        std::string vec3_to_string(Math::Vector3D vector)
        {
            std::ostringstream ss;
            ss << static_cast<int>(vector.x * 255) << " "
            << static_cast<int>(vector.y * 255) << " "
            << static_cast<int>(vector.z * 255) << "\n";
            return ss.str();
        }
};

#endif /* !PPM_FILE_HPP_ */

here is a sample main function that makes the program segfault

#include "src/Output/PPM_file.hpp"

int main()
{
    std::cout << "This line will never get executed, the program crashes as soon as a function containing the problematic piece of code is called" << std::endl;
    PPM_file<800, 600> test_file("image.ppm");
    return 0;
}

For some reasons, the segfault disapears when I remove the inheritance from IOutput and remove everything linked to IOutput in PPM_file, so I assume it is somehow linked but I can't figure out how

Upvotes: 1

Views: 48

Answers (0)

Related Questions