C++ 如何在函数模板中使用前向声明的datamembers?(C+;+;)

C++ 如何在函数模板中使用前向声明的datamembers?(C+;+;),c++,templates,C++,Templates,所以我有一个类,在其中我使用前向声明类的datamembers。现在我需要我的类的函数模板,但函数模板需要在头文件中实现,所以我不能访问我的成员。我怎样才能解决这个问题 这是我的一些代码 class Cell; class Node; class Wall : public WallAttributes { public: /// virtual ~Wall() {} private: Cell* m_c1; /

所以我有一个类,在其中我使用前向声明类的datamembers。现在我需要我的类的函数模板,但函数模板需要在头文件中实现,所以我不能访问我的成员。我怎样才能解决这个问题

这是我的一些代码

class Cell;
class Node;


class Wall : public WallAttributes
{
public:
    ///
    virtual ~Wall() {}

private:
    Cell*             m_c1;                ///<
    Cell*             m_c2;                ///<
    Node*             m_n1;                ///<
    Node*             m_n2;                ///<
    unsigned int      m_wall_index;        ///<

private:
    mutable double    m_length;            ///< Length is tracked lazily.
    mutable bool      m_length_dirty;      ///< Marks length dirty.

private:
    friend class cereal::access;
    template<class Archive>
    void save(Archive & archive) const
    {
        archive(m_c1->GetIndex());
        archive(m_c2->GetIndex());
        archive(m_n1->GetIndex());
        archive(m_n2->GetIndex());
        archive(m_wall_index);
        archive(m_length);
        archive(m_length_dirty);
    }

    template<class Archive>
    void load(Archive & archive)
    {
    //Todo
    }

};
类单元;
类节点;
类墙:公共wallettributes
{
公众:
///
虚拟~Wall(){}
私人:
单元*m_c1///<
单元*m_c2///<
节点*m_n1///<
节点*m_n2///<
无符号整数m_wall_索引///<
私人:
可变双m_长度;//<长度被延迟跟踪。
可变布尔m_length_dirty;//<标记长度dirty。
私人:
好友类:访问;
模板
无效保存(存档和存档)常量
{
存档(m_c1->GetIndex());
存档(m_c2->GetIndex());
存档(m_n1->GetIndex());
存档(m_n2->GetIndex());
档案(m_wall_索引);
档案(单位长度);
存档(m_长度_脏);
}
模板
无效加载(存档和存档)
{
//待办事项
}
};
这会导致错误:不完整类型单元格的使用无效

请尝试以下方法:

class Wall : public WallAttributes {
// ...
private: 
  template<class Archive>
  void load(Archive& archive);
};

// ...

#include "wall.tpp" // templates definitions
然后,您可以在包含“wall.tpp”之前或在该文件中包含
单元格的标题

或者,您也可以使用此方法:

wall.tpp

template<class Archive>
void Wall::load(Archive& archive) {
  // ..
}
template<>
void Wall::load<Cell>(Cell& archive); // declare template specialization for Cell type

可以将模板定义移动到源文件(Wall.cpp)

将标题更改为:

class Wall : public WallAttributes{
private:
    template<class Archive>
    void save(Archive & archive) const;

    template<class Archive>
    void load(Archive & archive);
}
类墙:公共Wallet属性{
私人:
模板
作废保存(存档和存档)常数;
模板
无效加载(归档和归档);
}
在Wall.cpp上:

template<class Archive>
void save(Archive & archive) const
{
    (...)
}

template<class Archive>
void load(Archive & archive)
{
    (...)
}
模板
无效保存(存档和存档)常量
{
(...)
}
模板
无效加载(存档和存档)
{
(...)
}

因为模板函数是私有的,所以我假设它们只在Wall.cpp中使用。但如果不是这样,您可以使用模板定义创建一个中间cpp文件,如Wall-templates.cpp,并将该cpp文件包含在您的Wall.cpp中。

为什么不能完整定义
单元格和
节点
?创建一个具有纯虚拟函数的基本归档类来执行任何操作。使用一些包装类和指针或实际归档类的实例从归档类型继承,并在运行时传递。现在您可以创建一个非模板函数,该函数引用您的存档基类。@jrok以避免标头膨胀?这是一个很好的技巧。由于您使用的成员包括
单元格
节点
,因此您需要这些类的完整定义,否则编译器将不知道它们有哪些成员。这不是我的代码,我的任务是使项目可序列化,这样我就不能更改代码的结构。这如何解决定义不完整的问题?对,我已经解决了这个问题。它们是私有的,但在它们上面有一个
friend
声明。我怀疑这就是它们应该被调用的地方。好吧,这就是为什么我添加了在“Wall templates.cpp”中放置定义的可能性
template<class Archive>
void save(Archive & archive) const
{
    (...)
}

template<class Archive>
void load(Archive & archive)
{
    (...)
}