0

I cannot use reference to incomplate (forward declared) class as template for list. But pointer works fine. For what I've read incomplete types are allowed for vector, list and forward list (and not allowed for map, set and others)

Here is example

#include <list>
#include <vector>

class MyClass;

void foo(const MyClass&);            //works fine
std::vector<const MyClass&> ref_vec; //error
std::list<const MyClass&> ref_list;  //error
std::vector<const MyClass*> p_vec;   //works fine
std::list<const MyClass*> p_list;    //works fine

class MyClass
{};

void main(){}
Demaunt
  • 1,183
  • 2
  • 16
  • 26
  • 6
    This has nothing to do with incomplete types. You can't have a `std::vector` of references for the same reason you can't have an array of references (e.g. `int& arr[5]`). – DeiDei May 07 '19 at 19:51
  • 4
    Use `std::reference_wrapper` instead of raw references – Daniel Jour May 07 '19 at 19:52
  • 2
    Also: `void main()` --> **NO** Use `int main()` – Daniel Jour May 07 '19 at 19:52
  • 1
    I think, it would be more straightforward to store pointers in the containers. – SergeyA May 07 '19 at 19:56
  • 1
    @SergeyA Suggestion to use raw points seems to be pretty wild in 2019 – user7860670 May 07 '19 at 20:00
  • 2
    @VTT Depends if they are owning pointers or not. – François Andrieux May 07 '19 at 20:01
  • If you replace your forward declaration with a full class definition instead, you get the same problem. This has nothing to do with forward declaration, it's a red herring. – François Andrieux May 07 '19 at 20:02
  • 1
    what is the question actually? what do you want to achieve? I mean your results are correct, just your interpretation is off. You would like to have a `std::vector` ? – 463035818_is_not_an_ai May 07 '19 at 20:03
  • 1
    @VTT how is `std::ref` better than naked pointer? Also, a vector of non-owning naked pointer is perfectly fine. Suggestion to not understand the difference between owning and non-owning pointers and a mantra 'never use naked pointers' seem pretty wild to me. – SergeyA May 07 '19 at 20:33
  • @SergeyA reference wrapper will save you a lot of efforts spent on writing and maintaining: no need to write comments at every place where those pointers are being passed around whether those pointers are not owning and whether they point at a single object or at many; since raw pointers are nullable they will also require comments, annotations and checks of their optionality. Unless one is dealing with C or some third party interop pointers seem like a huge waste of time. – user7860670 May 07 '19 at 21:28

1 Answers1

0

The problem here does not have anything to do with forward declaration. You can see this by changing the program to this:

#include <list>
#include <vector>

class MyClass
{};

void foo(const MyClass&);            //works fine
std::vector<const MyClass&> ref_vec; //error
std::list<const MyClass&> ref_list;  //error
std::vector<const MyClass*> p_vec;   //works fine
std::list<const MyClass*> p_list;    //works fine

int main(){}

The lines marked as //error and /works fine will fail in the exact same manner. The problem is that std::vector and std::list are not allowed to have a type which is a reference. The reason for this in C++11 and beyond is that elements must be Erasable, which references are not (more details are in the question Why can't I make a vector of references?).

Travis Gockel
  • 26,877
  • 14
  • 89
  • 116