I am learning how to use std::optional
, and I am having trouble passing a std::optional<Type>
parameter to a function, since Type contains within it a std::unique_ptr
, which prevents the call.
What is the correct way to pass such a variable (std::optional<Type>
) to a function?
Here is a code snippet that easily reproduces the problem:
#include <iostream>
#include <optional>
#include <memory>
using namespace std;
struct myStruct
{
std::unique_ptr<int> a;
};
int func(const myStruct& val, std::optional<myStruct> opt)
{
if (opt.has_value())
{
return *(opt.value().a);
}
else
{
return *(val.a);
}
}
int main()
{
cout << "Hello World";
myStruct val;
val.a = std::make_unique<int>(5);
std::optional<myStruct> opt = std::nullopt;
myStruct temp;
temp.a = std::make_unique<int>(10);
opt = std::move(temp);
std::cout << "result is " << func(val, opt) << std::endl;
return 0;
}
The error I see for the code above:
main.cpp:35:47: error: use of deleted function ‘std::optional::optional(const std::optional&)’
std::cout << "result is " << func(val, opt) << std::endl;
^
In file included from main.cpp:10:0:
/usr/include/c++/7/optional:453:11: note: ‘std::optional::optional(const std::optional&)’ is implicitly deleted because the default definition would be ill-formed:
class optional
^~~~~~~~
/usr/include/c++/7/optional:453:11: error: use of deleted function ‘constexpr std::_Enable_copy_move::_Enable_copy_move(const std::_Enable_copy_move&) [with _Tag = std::optional]’
In file included from /usr/include/c++/7/optional:43:0,
from main.cpp:10:
/usr/include/c++/7/bits/enable_special_members.h:157:15: note: declared here
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
Your myStruct
is indirectly only movable (non-copyable), because of the member std::unique_ptr<int> a;
, which is also by default non-copyable (only move is allowed).
Therefore the optional variable opt
(which contains the struct myStruct
) is also indirectly only movable. However, in your function func
you are trying to pass opt
by value, which in effect tries to copy the underlying struct and hence the compiler error.
You need to pass opt
by const ref, as you are not modifying opt
anyway.
int func(const myStruct& val, const std::optional<myStruct>& opt)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
// ..code
}