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

Leo*_*Leo 3 c++ templates c++11 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
  {}

  ...

};
Run Code Online (Sandbox Code Playgroud)

我很困惑我应该如何在构造函数std::vector中用n_vstd::deques初始化。

子类声明了一个类似vectordeques 并按预期编译/工作(直到我将 s 添加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
  { }

  ...

};
Run Code Online (Sandbox Code Playgroud)

因此,这似乎与作为 的容器有关std::shared_ptr<entity<ComponentManager>>,但我不明白为什么会出现问题(entity包含标头,<ComponentManager>按照您的预期采用 a ,并ComponentManager在使用所有这些类时提供a )。

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

更新

这是代码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) {}
};
Run Code Online (Sandbox Code Playgroud)

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

template<typename ComponentManager> using entity_ptr_deque = std::deque<shared_ptr<entity<ComponentManager>>>;
Run Code Online (Sandbox Code Playgroud)

然后entity_ptr_deque<ComponentManager适当地替换。这有助于提高可读性,所以我可能会保留它,但这无助于理解错误,尤其是当一个最小的示例构建良好时(见评论)。

更新 2

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

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

declaration of 'auto component_collection<ComponentManager>::entity(int)' 
changes meaning of 'entity'
Run Code Online (Sandbox Code Playgroud)

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

Leo*_*Leo 6

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

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

可能X传递给的任何东西都需要一个值而不是一个类型,即 Clang 不认为这是一个模板。

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

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