4

I am getting the following error: 'ComponentManager' does not refer to a value when compiling a subclass which inherits from this parent class:

template<typename ComponentManager>
class component_collection {
protected:
  int n_components;
  int n_versions;
  int first_blank;
  int last_used;
  std::vector<std::deque<shared_ptr<entity<ComponentManager>>>> entity_pointers;

public:
  component_collection(int n_c, int n_v) :
    n_components(n_c),
    n_versions(n_v),
    first_blank(0),
    last_used(0),
    entity_pointers(n_v, std::deque<shared_ptr<entity<ComponentManager>>>()) // <-- ERROR HERE
  {}

  ...

};

I am confused as to how I should initialise the std::vector with n_v empty std::deques in the constructor.

The sub-class declares a similar vector of deques and compiles / worked as expected (until I added the vector<deque> to the parent, that is):

template<typename ComponentManager>
class test_component_collection : public component_collection<ComponentManager> {
  std::vector<std::deque<int>> values;

public:
  test_component_collection(int n_c, int n_v) :
      component_collection<ComponentManager>(n_c, n_v),
      values(n_v, std::deque<int>()) // <-- NO ERROR HERE
  { }

  ...

};

So it seems this is something to do with this being a container of std::shared_ptr<entity<ComponentManager>>, but I don't see why that would be a problem (the entity header is included, takes a <ComponentManager> as you would expect, and a ComponentManager is provided when all these classes are used).

I am clearly missing something...

Update

Here's the code for entity:

template<typename ComponentManager>
class entity {
protected:
  ComponentManager & component_manager;

public:
  entity(ComponentManager & cm) : component_manager(cm) {}
  void initialise_components(shared_ptr<entity<ComponentManager>> sp) {}
};

Adding this at the top of component_collection seems to fix things (the compilation error at least, I've not thoroughly tested the results):

template<typename ComponentManager> using entity_ptr_deque = std::deque<shared_ptr<entity<ComponentManager>>>;

And then substituting entity_ptr_deque<ComponentManager in as appropriate. This aids readability, so I might leave it in anyway, but it doesn't help understand the error, especially as a minimal example builds fine (see comments).

Update 2

Using Wandbox from the comments, I found that my full class didn't compile, while the version edited by @VittorioRomeo did.

Switching from Clang to GCC on Wandbox (I'm using Clang locally) gave a very different error message:

declaration of 'auto component_collection<ComponentManager>::entity(int)' 
changes meaning of 'entity'

This is a method that was present before I added the std::vector<std::deque<shared_ptr<entity<ComponentManager>>>> entity_pointers; and associated constructor update. It of course masks the name entity in the class definition, hence the error. Clang's error message pointed somewhere else entirely.

Leo
  • 4,217
  • 4
  • 25
  • 41
  • 3
    Cannot reproduce [on a minimal example](http://melpon.org/wandbox/permlink/yq2UDKDnjzWO8fYZ) – Vittorio Romeo Dec 19 '16 at 12:17
  • 3
    Try initializing `values` just with `values(n_v)`. Default initialization of the filling element is the default. Not an answer, but might give some more insight into what's happening. – The Vee Dec 19 '16 at 12:18
  • 1
    Can you post the declaration of the `entity` template or the header you're including? – The Vee Dec 19 '16 at 12:23
  • I've added `entity`. I'm not entirely surprised the minimal example builds okay – I can't see why this wouldn't! Any thoughts where else to look? I haven't edited the pasted code at all, except to remove some member functions, but I don't see how they could affect this. – Leo Dec 19 '16 at 12:26
  • So defining the `deque<...` as a type alias seems to work. I'll update again above... – Leo Dec 19 '16 at 12:28
  • Yep @TheVee it does compile when I don't specify the type in the `deque` constructor. Doesn't quite get to the bottom of things, but thanks. – Leo Dec 19 '16 at 12:34
  • Let's see if there's more. Is it `std::shared_ptr` you're using or your own? I'm finding it suspicious that all the other STL entities have a fully qualified name but this is only used as a `shared_ptr`. – The Vee Dec 19 '16 at 12:51
  • Good thought, but I'm afraid it's just `std::shared_ptr`. Should've included the `using...` in the code, sorry. – Leo Dec 19 '16 at 13:12
  • Okay, so playing with my code vs what @VittorioRomeo helpfully put together (WandBox is incredibly useful, I've not seen it before), I've solved this. Turns out I was asking the wrong question really... What's the etiquette here? Should I post an answer / change the question / ask the 'correct' question separately? – Leo Dec 20 '16 at 15:32
  • @Leo Posting a self-answer to this is a good way out, and if you're interested in something else, ask another question. In the specific case of the resolution that you found I think that makes the question border on point 2 [here](http://stackoverflow.com/help/on-topic), however. – The Vee Dec 20 '16 at 16:16

1 Answers1

6

The Clang compilation error 'X' does not refer to a value can be misleading.

It means, at that point in the code, Clang is expecting a value, not a type. But the reason for that may be nothing to do with the nature of X.

It may be that whatever X is being passed to expects a value rather than a type, i.e. Clang does not think this is a template.

Specifically in this case: template<typename ComponentManager> entity has been masked by a method in the class – auto entity(int). This changes the meaning of entity, causing an error at the site of the template specialisation, but not at the site of the method which is doing the masking.

GCC gives a much clearer error message in this instance, so it's worth trying a tool like Wandbox to see what different compilers think is wrong with the code.

Leo
  • 4,217
  • 4
  • 25
  • 41