C2664 无法转换为 && 值
C2664 cannot convert to && value
编译器希望我的左值成为右值引用,但我不明白为什么。
我的问题是:
- 为什么“dataLen”是常量,即使它被声明为非常量并且 lambda 被告知默认通过引用捕获?
- 为什么编译器尝试转换为右值引用“unsigned __int64 &&”,即使它被声明为“unsigned long long”(无右值引用)tupleByteVector_content?
我认为这是因为 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 指针没有转换(我自己免费翻译成英文)
dataLen
被视为 const 因为您按值捕获它:
[&, this, dataLen,
^^^
默认情况下,为闭包生成的函数调用运算符被标记为const,因此在const 方法中您只能读取数据。不允许修改,除非您将 mutable
添加到 lambda 的定义中。
当您使用 make_tuple
时,您应该依赖模板参数推导,而不是像您那样以显式方式放置类型。您的问题的简短版本:
int i;
std::tuple<int> t = std::make_tuple<int>(i);
i
是命名对象,所以是lvalue。通过 make_tuple<int>
,您使 make_tuple
签名看起来像:make_tuple(int&&)
。这是编译器抱怨的地方,因为 i
作为 lvalue 不能绑定到 rvalue 引用。通过参数推导,make_tuple
的参数被推导为:int&
,此时i
可以被绑定。
push_back
on vector
不起作用,因为您再次按值捕获矢量。 push_back
修改对象,这在调用 const 对象时是不允许的。您应该通过引用捕获它。
编译器希望我的左值成为右值引用,但我不明白为什么。
我的问题是:
- 为什么“dataLen”是常量,即使它被声明为非常量并且 lambda 被告知默认通过引用捕获?
- 为什么编译器尝试转换为右值引用“unsigned __int64 &&”,即使它被声明为“unsigned long long”(无右值引用)tupleByteVector_content?
我认为这是因为 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 指针没有转换(我自己免费翻译成英文)
dataLen
被视为 const 因为您按值捕获它:[&, this, dataLen, ^^^
默认情况下,为闭包生成的函数调用运算符被标记为const,因此在const 方法中您只能读取数据。不允许修改,除非您将 mutable
添加到 lambda 的定义中。
当您使用
make_tuple
时,您应该依赖模板参数推导,而不是像您那样以显式方式放置类型。您的问题的简短版本:int i; std::tuple<int> t = std::make_tuple<int>(i);
i
是命名对象,所以是lvalue。通过 make_tuple<int>
,您使 make_tuple
签名看起来像:make_tuple(int&&)
。这是编译器抱怨的地方,因为 i
作为 lvalue 不能绑定到 rvalue 引用。通过参数推导,make_tuple
的参数被推导为:int&
,此时i
可以被绑定。
push_back
on vector
不起作用,因为您再次按值捕获矢量。 push_back
修改对象,这在调用 const 对象时是不允许的。您应该通过引用捕获它。