This is my test code:
#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;
}
The code fails to compile with the following error:
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.
I am positive that the error stems from my usage of decltype
to specify the type of the second vector VD2
. Why does the usage result in the error, since *iter
should yield me an object whose type is data
?
Secondly, I am certainly more puzzled by the error reported by the compiler; just reading the report doesn't help me understand what the error is that the compiler is trying to convey.
Look forward to some clarification.
I am positive that the error stems from my usage of
decltype
to specify the type of the second vectorVD2
[...]
Yes, you are right about this. The decltype(*iter)
yields a reference type (data&
). Vectors must store objects, not references. So vector<decltype(*iter)>
becomes vector<data&>
. But std::vector<data&>
is illegal because:
std::allocator<data&>
tries to create data&*
(a pointer to a reference), which is invalid C++.
The compiler error "forming pointer to reference type ‘func()::data&’" is explaining exactly that—you can’t have pointers to references—hence the allocator fails to compile.
That’s why you're seeing the error deep inside the instantiation of vector<...>
.
How to fix it?
If you want a vector of copies of the objects, use the unqualified object type:
using value_type = std::decay_t<decltype(*iter)>; // strips reference and cv-qualifiers
std::vector<value_type> vD2;
Or more idiomatically:
std::vector<typename std::vector<data>::value_type> vD2;
This yields vector, which is valid.
If you intentionally want to store references (very rare), you’d need std::reference_wrapper<data>
:
std::vector<std::reference_wrapper<data>> vD2; // With `#include <functional>`