模板编译错误:"X"不引用值

Template compilation error: 'X' does not refer to a value

本文关键字:引用 编译 错误      更新时间:2023-10-16

>我收到以下错误:编译从此父类继承的子类时'ComponentManager' does not refer to a value

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
{}
...
};

我对如何在构造函数中使用n_vstd::deque初始化std::vector感到困惑。

子类声明了类似的dequesvector并按预期编译/工作(直到我将vector<deque>添加到父级,即):

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
{ }
...
};

所以这似乎与它是std::shared_ptr<entity<ComponentManager>>的容器有关,但我不明白为什么这会是一个问题(包含entity标头,如您所料<ComponentManager>,并且在使用所有这些类时提供ComponentManager)。

我显然错过了一些东西...

更新

这是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) {}
};

component_collection顶部添加它似乎可以解决问题(至少编译错误,我没有彻底测试结果):

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

然后酌情替换entity_ptr_deque<ComponentManager。这有助于可读性,所以我可能会把它留在里面,但它无助于理解错误,特别是因为最小示例构建良好(请参阅注释)。

更新 2

使用评论中的Wandbox,我发现我的完整类没有编译,而@VittorioRomeo编辑的版本可以编译。

在Wandbox上从Clang切换到GCC(我在本地使用Clang)给出了一个非常不同的错误消息:

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

这是我添加std::vector<std::deque<shared_ptr<entity<ComponentManager>>>> entity_pointers;和关联的构造函数更新之前存在的方法。当然,它会屏蔽类定义中的名称entity,因此会出现错误。Clang的错误消息完全指向其他地方。

Clang 编译错误'X' does not refer to a value可能会产生误导。

这意味着,在代码中的这一点上,Clang 需要的值,而不是类型。但究其原因,可能与X的性质无关。

可能是传递的任何X都期望值而不是类型,即 Clang 不认为这是一个模板。

具体在这种情况下:template<typename ComponentManager> entity已被类中的方法屏蔽 –auto entity(int).这改变了entity的含义,导致模板专用化站点的错误,但不会在进行掩码的方法站点上出错

在这种情况下,GCC 给出了更清晰的错误消息,因此值得尝试像 Wandbox 这样的工具,看看不同的编译器认为代码出了什么问题。