C++ 将 vector<Class*> 传递给模板成员

C++ passing vector<Class*> to template member

本文关键字:成员 vector lt Class C++ gt      更新时间:2023-10-16

我已经坐了很长一段时间了。我只是找不到答案,所以如果你们能帮忙,那就太好了。

涉及两个类,其中一个(XMLParser)从ifstream中读取并反序列化对象,并将它们存储在本地veriable中。第二个是保持一个vector<Someclass *> objVec;,因此是一个保持指向特定类型对象的指针的向量。我把这一切都像这样拼凑起来:

ifstream file(filename, ifstream::in);
if (file.is_open())
{
    XMLParser xmlParser;
    file >> xmlParser;
    xmlParser.fill(&objVec);
    file.close();
}

XMLParser.h:

class XMLParser
{
private:
vector<Someclass> someVec;
vector<SomeOtherclass> someOtherVec;
public:
    template<class T> void fill(std::vector<T*> *vec);
    friend std::istream &operator>>(std::istream &stream, XMLParser &ob);
};
std::istream& operator>>(std::istream &stream, XMLParser &ob);

XMLParser.cpp:

std::istream& operator>>(std::istream &stream, XMLParser &ob)
{
    //deserialize objects from stream and store them locally
    return stream;
}
template <class T> void XMLParser::fill(std::vector<T*> *vec)
{
    //fill the vector with the right objects
}

一切都编译得很好,没有错误或警告。但是当链接的时候,我会得到一个undefined reference to 'void XMLParser::fill<Someclass>(std::vector<SomeClass*, std::allocator<Someclass*> >*)',当然会提供XMLParser.o。

我尝试过的,以及其他事情:包括分配器:template<class T> void fill(std::vector<T*, std::allocator<T*> > *vec)->相同错误为填充宽度Someclass:template <> void XMLParser::fill(std::vector<Someclass*> *vec)->正在工作!但不是我想要的

我在网上搜索了一些例子,但没有一个提供模板的分配器类,所以这不是问题所在。专业化正在发挥作用,但有人知道为什么我需要为每一个可能出现的班级提供专业化吗?有办法绕过吗?因为如果我必须为XML中的每个类提供一个专门化,那么它就不会非常通用。

谢谢Martin

您需要在头文件中定义模板,而不是在.cpp文件中定义。该标准要求模板定义存在于其声明的每个翻译单元中(如果使用)。

有两种方法可以解决此问题。第一种,也是迄今为止最常见的一种,是将模板减速度放在h文件中(不仅仅是定义)。这可以通过在h中写入来完成,也可以(不太常见)在h中包括.cpp文件。

另一种选择是在cpp文件中为要使用的每种类型显式实例化模板。

标准声明了另一个选项:在模板减速之前使用"export",同时将定义保留在cpp文件中。然而,我不知道有哪个编译器真正支持这一点(它可能在当前标准中也被删除了)。这样做的问题是,如果使用它,cpp编译之间存在依赖关系(我可以在不更改h文件的情况下更改模板定义,并且所有使用此模板的cpp文件都必须重新编译(即使h没有更改…)