返回 std::Optional<T> 而不复制

CAN*_*VAS 2 c++ c++17 stdoptional

我目前正在学习 OpenGL,并在编写着色器抽象类时选择std::optional用于错误处理。现在为了防止意外的双重释放,我将删除复制构造函数

// Shader.h
Shader(const Shader&) = delete;
Shader& operator=(const Shader&) = delete;
Run Code Online (Sandbox Code Playgroud)

但回来时

// Shader.cpp
return std::make_optional<Shader>(Shader(id));
Run Code Online (Sandbox Code Playgroud)

在静态函数中fromSrc它给了我一个编译错误

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

我正在使用 Visual Studio 2022 (MSVC v143) 和 c++17

编辑:我被告知要实现移动构造函数,这是一个很好的实现吗?

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

Hol*_*Cat 6

使你的包装器不可复制固然很好,但使它们不可移动则是死胡同。

复制和交换习惯使编写移动操作变得轻而易举:

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 */}
};
Run Code Online (Sandbox Code Playgroud)

您不再需要手动删除复制操作,因为执行移动操作会自动执行此操作。