如何用decltype实例化std::vector?编译报错原因解析
问题分析:使用
decltype(*iter)实例化std::vector失败的原因 问题描述
尝试使用decltype(*iter)实例化std::vector vD2时编译失败,报错信息为“forming pointer to reference type ‘func()::data&’”,存在两个疑惑:
- 为什么
*iter的类型不是data? - 该编译错误的具体含义是什么?
测试代码
#include<vector> #include<iostream> #include<type_traits> using std::vector; using std::is_same_v; using std::cout; using std::endl; int func() { struct data { int i; char c; }; vector<data> vD1; vD1.push_back(data()); vD1.at(0).i = 0; vD1.at(0).c = 'a'; auto iter = vD1.begin(); vector<decltype(*iter)>vD2; if(is_same_v<decltype(vD1),decltype(vD2)>) { cout << "similar types" << endl; } else { cout << "dissimilar types" << endl; } return 0; } int main() { auto exit = (int (*)()) &func; std::cout << exit() << std::endl; }
编译报错信息
g++ -c -o code.o code.cpp -ggdb -g3 -pedantic-errors -Wall -Wextra -Wfatal-errors -Wpedantic -std=c++20 In file included from /usr/include/c++/11/x86_64-redhat-linux/bits/c++allocator.h:33, from /usr/include/c++/11/bits/allocator.h:46, from /usr/include/c++/11/vector:64, from code.cpp:1: /usr/include/c++/11/ext/new_allocator.h: In instantiation of ‘class __gnu_cxx::new_allocator<func()::data&>’: /usr/include/c++/11/bits/allocator.h:124:11: required from ‘class std::allocator<func()::data&>’ /usr/include/c++/11/bits/stl_vector.h:87:21: required from ‘struct std::_Vector_base<func()::data&, std::allocator<func()::data&> >’ /usr/include/c++/11/bits/stl_vector.h:389:11: required from ‘class std::vector<func()::data&>’ code.cpp:25:26: required from here /usr/include/c++/11/ext/new_allocator.h:103:7: error: forming pointer to reference type ‘func()::data&’ 103 | allocate(size_type __n, const void* = static_cast<const void*>(0)) | ^~~~~~~~ compilation terminated due to -Wfatal-errors.
问题解答
为什么
decltype(*iter)是data&而非data?std::vector的迭代器解引用(operator*)返回的是容器元素的左值引用——你可以通过*iter修改容器内的元素,证明这是左值。而decltype的推导规则是:如果表达式是左值,推导结果会保留引用属性,因此decltype(*iter)得到的类型是data&,而非原始的data类型。编译错误的含义是什么?
std::vector的模板参数要求是可分配内存的对象类型,但引用不是独立对象,只是另一个对象的别名,无法单独占用内存。当实例化vector<data&>时,vector底层的分配器会尝试创建指向data&的指针(即data&*),但C++语法明确禁止“指向引用的指针”这种类型,因此编译器抛出该错误。
解决方法
要通过迭代器推导得到元素的原始类型,需要用std::remove_reference_t去除引用属性:
vector<std::remove_reference_t<decltype(*iter)>> vD2;
或者更直接地使用容器的value_type:
vector<decltype(vD1)::value_type> vD2;
修改后,vD2的类型会和vD1一致,编译即可通过。
内容的提问来源于stack exchange,提问作者Vinod
相关产品推荐
相关产品推荐

