3

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.

3
  • 1
    Oftentimes clang is a bit more helpful in error messages than gcc. Here it mentions that you're trying to instantiate vector<data&> relatively early on: <source>:25:26: note: in instantiation of template class 'std::vector<data &>' requested here 25 | vector<decltype(*iter)>vD2; godbolt.org/z/rPrKEnahf Commented Jul 11 at 10:56
  • std::vector<std::remove_cvref_t<decltype(*iter)>> Commented Jul 11 at 12:20
  • 1
    You are trying to create a vector of references *iter is a `func&" (not a func) and MSVC is really clear about this : static_assert failed: The C++ Standard forbids allocators for reference elements because of [allocator.requirements].. Commented Jul 11 at 12:55

2 Answers 2

4

I am positive that the error stems from my usage of decltype to specify the type of the second vector VD2 [...]

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>`
Sign up to request clarification or add additional context in comments.

Comments

2

decltype(*iter) is data& and you cannot make a vector of references.

you want to use std::decay_t to remove the const/ref/volatile qualifications of the type.

vector<std::decay_t<decltype(*iter)>> vD2;

online demo

If you want a vector of references then you need std::reference_wrapper as the element type.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.