1

编译器希望我的左值成为右值引用,我不明白为什么。

我的问题是:

  1. 为什么“dataLen”是 const,即使它被声明为非 const 并且 lambda 被告知默认通过引用捕获?
  2. 为什么编译器尝试转换为右值引用“unsigned __int64 &&”,即使它被声明为 tupleByteVector_content 的“unsigned long long”(无右值引用)?

我认为这是因为 lambda 捕获,但请参阅下面的简化工作流程:

void read_socket()
{
  std::vector<std::tuple<unsigned long long, std::vector<unsigned char>>> tupleByteVector_content;
  read_socket_readSome(tupleByteVector_content, [this, &tupleByteVector_content]() {
    //use tuple vector
  });
}

//catch the tuple vector by reference
void read_socket_readSome(std::vector<std::tuple<unsigned long long, const std::shared_ptr<Session>& session, std::vector<unsigned char>>> & tupleByteVector_content, std::function<void()> && continueReadFunction)
{
  //Read data length from a asio socket
  std::shared_ptr<asio::streambuf> len_buffer = std::make_shared<asio::streambuf>();
  asio::async_read(session->connection->socket->next_layer(), *len_buffer, asio::transfer_exactly(1), [&, 
  this, session, len_buffer, tupleByteVector_content, continueReadFunction](const error_code& ec, std::size_t bytes_transferred) {

    //the first value I want to save
    unsigned long long dataLen = BytesToLength(len_buffer);

    //Read data from a asio socket
    std::shared_ptr<asio::streambuf> data_buffer = std::make_shared<asio::streambuf>();
    asio::async_read(session->connection->socket->next_layer(), *data_buffer, asio::transfer_exactly(dataLen), [&, this, dataLen, data_buffer, tupleByteVector_content, session, continueReadFunction](const error_code& ec, std::size_t bytes_transferred) {

        //ERROR HERE: ----------->

        std::tuple<unsigned long long, std::vector<unsigned char>> t = 
          std::make_tuple<unsigned long long, std::vector<unsigned char>>(

          dataLen, // ERROR C2664, cant convert argument 1 from "const unsigned __int64" to "unsigned __int64 &&"

          { asio::buffers_begin(data_buffer->data()), asio::buffers_end(data_buffer->data()) });

        //ERROR HERE: <-----------
        
        tupleByteVector_content.push_back(t);

        continueReadFunction();

    });
  });
}

编辑:我能够编译这个元组:

std::tuple<unsigned long long, std::vector<unsigned char>> t = { dataLen, { asio::buffers_begin(data_buffer->data()), asio::buffers_end(data_buffer->data()) } };

但是随后向量的 push_back 给出了错误:错误 C2663: [...] ::push_back": 对于 2 个重载,this 指针没有转换(我自己免费翻译成英文)

4

1 回答 1

4
  1. dataLen被视为const因为您按值捕获它:

    [&, this, dataLen,
              ^^^
    

默认情况下,为闭包生成的函数调用运算符被标记为const,因此在 const 方法中您只能读取数据。不允许修改,除非您添加mutable到 lambda 的定义。

  1. 当您使用时,make_tuple您应该依赖模板参数推导,而不是像您所做的那样以显式方式放置类型。您的问题的简短版本:

     int i;
     std::tuple<int> t = std::make_tuple<int>(i);
    

i被命名为对象,所以它是lvalue。通过make_tuple<int>您使make_tuple签名看起来像:make_tuple(int&&)。这是编译器抱怨的地方,因为i不能绑定到右值引用。通过参数推导,参数 ofmake_tuple被推导为: int&,并且在这种情况下i可以绑定。

push_backonvector不起作用,因为您再次按值捕获了向量。修改对象,在调用const对象push_back时是不允许的。您应该通过引用来捕获它。

于 2020-07-14T12:43:50.983 回答