问题
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::deque
s in the constructor.
The sub-class declares a similar vector
of deque
s 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.
回答1:
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.
来源:https://stackoverflow.com/questions/41222330/template-compilation-error-x-does-not-refer-to-a-value