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

时间:2016-12-19 12:12:33

标签: c++ c++11 templates c++14

我在编译继承自此父类的子类时遇到以下错误:'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
  {}

  ...

};

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

子类声明类似vector deque并按预期编译/工作(直到我将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> 1}}正如您所期望的那样,并且在使用所有这些类时提供了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的错误信息完全指向其他地方。

1 个答案:

答案 0 :(得分:4)

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

这意味着,在代码中的那一点,Clang期待,而不是类型。但其原因可能与X的性质无关。

可能是,无论X传递给 ,都需要一个值而不是一个类型,即Clang不认为这是一个模板。

特别是在这种情况下:template<typename ComponentManager> entity已被类中的方法屏蔽 - auto entity(int)。这会更改entity的含义,导致模板特化的站点出错,但在正在进行屏蔽的方法的站点上。

GCC在这个实例中提供了更清晰的错误消息,所以值得尝试像Wandbox这样的工具来查看不同的编译器认为代码有什么问题。