2

I'm currently learning OpenGL and while writing a shader abstraction class I chose std::optional for error handling. Now to prevent accidental double freeing, I'm removing the copy constructors with

// Shader.h
Shader(const Shader&) = delete;
Shader& operator=(const Shader&) = delete;

but when returning

// Shader.cpp
return std::make_optional<Shader>(Shader(id));

in the static function fromSrc it gives me a compile error

Error (active)  E0304   no instance of overloaded function "std::make_optional" matches the argument list   LearnOpengl *\LearnOpengl\LearnOpengl\src\util\Shader.cpp   90  

I'm using Visual Studio 2022 (MSVC v143) with c++17

Edit: I was told to implement a move constructor, is this a good implementation?

    Shader::Shader(Shader&& other) noexcept
        : m_Id(std::exchange(other.m_Id, 0)), 
        m_Destroyed(std::exchange(other.m_Destroyed, true)), 
        m_Uniforms(std::exchange(other.m_Uniforms, {})) {}

    Shader& Shader::operator=(Shader other) noexcept {
        std::swap(m_Id, other.m_Id);
        std::swap(m_Destroyed, other.m_Destroyed);
        std::swap(m_Uniforms, other.m_Uniforms);
        return *this;
    }
CANVAS
  • 31
  • 1
  • 4

1 Answers1

5

Making your wrappers non-copyable is good, but making them non-movable is a dead end.

The copy&swap idiom makes writing the move operations a no-brainer:

class Shader
{
    struct Data
    {
        int handle = 0; // For example.
        // More fields here, if needed.
        // You can get rid of the struct if there's only one. But if you do, make sure you use the same default value in the field initializer and in `std::exchange()` below.
    };
    Data data;

  public:
    Shader() {}
    // More constructors here.
   
    Shader(Shader &&other) noexcept : data(std::exchange(other.data, {})) {}
    Shader &operator=(Shader other) noexcept {std::swap(data, other.data); return *this;}

    ~Shader() {/* write me */}
};

You no longer need to manually delete the copy operations, since implementing the move operations does that automatically.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207