0

我正在尝试创建一个返回std::optionalto的函数Buffer

std::optional<Buffer> receive(SmolSocket smolSocket)
{
   //...
   return std::optional<Buffer>(buffer);
}

Buffer简单的在哪里

struct Buffer
{
public:
   std::unique_ptr<uint8_t[]> data;
   size_t len = 0;
   bool empty = false;

   Buffer(CBuffer cBuffer)
   {
      data = std::unique_ptr<uint8_t[]>(cBuffer.data);
      len = cBuffer.len;
   }

   Buffer(bool empty)
   {
      data = std::unique_ptr<uint8_t[]>(nullptr);
      this->len = 0;
      this->empty = empty;
   }

   uint8_t* getData()
   {
      return data.get();
   }
};

但我收到很多错误:

/workspaces/libopenvpnclient/src/libopenvpn/../../smoltcp_cpp_interface/src/virtual_tun/interface.h:283:52: error: no matching function for call to 'std::optional<smoltcp::Buffer>::optional(smoltcp::Buffer&)'
  283 |                 return std::optional<Buffer>(buffer);

/usr/include/c++/9/optional:760:2: note: candidate: 'template<class ... _Args, typename std::enable_if<__and_v<std::is_constructible<smoltcp::Buffer, _Args&& ...> >, bool>::type <anonymous> > constexpr std::optional<_Tp>::optional(std::in_place_t, _Args&& ...)'
  760 |  optional(in_place_t, _Args&&... __args)
      |  ^~~~~~~~
/usr/include/c++/9/optional:760:2: note:   template argument deduction/substitution failed:
/usr/include/c++/9/optional:758:56: error: no type named 'type' in 'struct std::enable_if<false, bool>'
  758 |         _Requires<is_constructible<_Tp, _Args&&...>> = false>

note:   'smoltcp::Buffer' is not derived from 'std::optional<_Tp>'
  283 |                 return std::optional<Buffer>(buffer);

std::optional在其他情况下使用过,我看不出这里有什么问题。

我也尝试使用return std::optional<Buffer>{buffer};.

4

2 回答 2

2

问题是,为了做到

std::optional<Buffer>(buffer);

您需要一个复制或移动构造函数。当您提供参数化构造函数(即Buffer(CBuffer cBuffer))时,编译器不会同时生成它们。所以你需要明确地提供它们。

但是,就您而言,您还有一个问题。该成员data是不可复制的(即std::unique_ptr<uint8_t[]>),这意味着您只能提供移动构造函数。

因此提供移动构造函数

struct Buffer
{
public:
   Buffer(Buffer&& rhs)
      : data{ std::move(rhs.data) }
      , len{rhs.len}
   {}
   // ... other code
};

buffer在函数中移动:

std::optional<Buffer> receive()
{
   // ...
   return std::optional<Buffer>(std::move(buffer));
}

见一个最小的示例演示

于 2020-07-29T17:35:14.650 回答
2

简而言之:您应该将复制或移动构造函数添加到Buffer.

更多细节:

您有Buffer对象并且需要创建另一个Buffer(in std::optional),但是没有Buffer可以接受您传递的参数的构造函数。编译器不会生成默认的复制/移动构造函数,因为您声明了自定义构造函数。因此,您应该使用or构造std::optional<Buffer>from bool、 fromCBuffer或添加另一个。const Buffer&Buffer&&

于 2020-07-29T17:23:44.270 回答