问题描述
我将用例简化为一个无意义的最小示例:
#include <vector>
template<typename Container>
void f(Container&) { // using && gives compilation error... (*)
std::vector<Container>{};
};
int main() {
std::vector<int> v;
f(v); // (*) ... which is "solved" by std::move-ing v here. Why?
}
进行编译。但是,当我添加另一个&
来使未命名的参数成为转发引用时,出现以下错误(使用g++ -std=c++11 thatfile.cpp
或-std=c++17
进行编译)。另一方面,std::move
在呼叫站点上v
解决了该问题。
我想了解原因。
In file included from /usr/include/c++/10.2.0/x86_64-pc-linux-gnu/bits/c++allocator.h:33,from /usr/include/c++/10.2.0/bits/allocator.h:46,from /usr/include/c++/10.2.0/vector:64,from prova.cpp:1:
/usr/include/c++/10.2.0/ext/new_allocator.h: In instantiation of ‘class __gnu_cxx::new_allocator<std::vector<int>&>’:
/usr/include/c++/10.2.0/bits/allocator.h:116:11: required from ‘class std::allocator<std::vector<int>&>’
/usr/include/c++/10.2.0/bits/stl_vector.h:87:21: required from ‘struct std::_Vector_base<std::vector<int>&,std::allocator<std::vector<int>&> >’
/usr/include/c++/10.2.0/bits/stl_vector.h:389:11: required from ‘class std::vector<std::vector<int>&,std::allocator<std::vector<int>&> >’
prova.cpp:5:5: required from ‘void f(Container&&) [with Container = std::vector<int>&]’
prova.cpp:10:8: required from here
/usr/include/c++/10.2.0/ext/new_allocator.h:62:26: error: forming pointer to reference type ‘std::vector<int>&’
62 | typedef _TP* pointer;
| ^~~~~~~
/usr/include/c++/10.2.0/ext/new_allocator.h:63:26: error: forming pointer to reference type ‘std::vector<int>&’
63 | typedef const _TP* const_pointer;
| ^~~~~~~~~~~~~
/usr/include/c++/10.2.0/ext/new_allocator.h:103:7: error: forming pointer to reference type ‘std::vector<int>&’
103 | allocate(size_type __n,const void* = static_cast<const void*>(0))
| ^~~~~~~~
/usr/include/c++/10.2.0/ext/new_allocator.h:120:7: error: forming pointer to reference type ‘std::vector<int>&’
120 | deallocate(_TP* __p,size_type __t)
| ^~~~~~~~~~
...
解决方法
有空的时候
template<typename Container>
void f(Container&) { // using && gives compilation error... (*)
std::vector<Container>{};
};
Constainer
被推导为std::vector
,一切都很好。使用时
template<typename Container>
void f(Container&&) { // using && gives compilation error... (*)
std::vector<Container>{};
};
并且您不使用std::move
,则Container
被推导为std::vector&
,这是一种引用类型,并且您不能创建引用类型的向量,因此得到错误。
当您使用std::move(v)
时,您将std::vector&&
传递给函数,因此Container
再次被推导为std::vector
,并且由于不是引用类型,因此代码得以编译