具有 STL 容器成员的模板类

template class with STL container member

本文关键字:成员 STL 具有      更新时间:2023-10-16

我正在编写一个使用 std::multimap 作为成员的模板类,并收到编译错误。

LocTree.h:

#pragma once
#include <map>
template <class Loc, class T>
class LocTree
{
public :
         typedef std::multimap<typename Loc, typename T> TreeType;
        LocTree( void );
        ~LocTree( void ) { };
private :
        TreeType db;
};

LocTree.cpp:

#include "StdAfx.h"
#include "LocTree.h"
LocTree< class Loc, class T>::LocTree()
{
}

编译错误(来自VC2005):

Error     1     error C2079: 'std::pair<_Ty1,_Ty2>::first' uses undefined class 'Loc'     c:program files (x86)microsoft visual studio 8vcincludeutility     53
Error     2     error C2079: 'std::pair<_Ty1,_Ty2>::second' uses undefined class 'T'     c:program files (x86)microsoft visual studio 8vcincludeutility     54

我知道我可以将函数定义放在 .h 中,但如果这样做是合法的,我希望将它们分开。 如何解决这个(可能是新手)问题?

构造函数定义应为:

template<class Loc, class T>
LocTree<Loc,T>::LocTree()
{
}

另外,希望将它们分开... - 不要 - 你在浪费你的时间。将它们分开的唯一方法是在不同的标头中有一个定义,您也包括该标头。因此,从技术上讲,它们是分开的,但实现仍然是可见的。

两点。 第一个是:什么是:

typedef std::multimap<typename Loc, typename T> TreeType;

应该是什么意思? 我看不出typename在那里做什么;我认为你只是想要:

typedef std::multimap<Loc, T> TreeType;

其次,在类,语法为:

template <typename Loc, typename T>
LocTree<Loc, T>::LocTree()
{
}

换句话说,您必须重复template<...>子句。 (是否你使用typenameclass<...>是无动于衷的。 既然它不一定是一堂课,我认识的大多数人都喜欢typename,因为这更接近于所表示的意思。

至于保持实现独立:C++中的模板是在这方面有些破碎。 你无法避免编译器屬地。 您仍然希望将实现与但是,定义。 通常的技术是放置模板在单独的文件中实现(例如,.tcc),并包括这是从标题。

将模板的实现分开并不是一件小事。

一般来说,这是无法做到的。也就是说,在模板化参数可能是"任何东西"的情况下,无法完成此操作。

对于模板化参数的特定有限子集,可以这样做,例如,如果您有这样的模板:

template< bool B > class Foo;

然后,您可以指定:

extern template class Foo<true>;
extern template class Foo<false>;

这称为"实例化"模板,并向编译器指定存在值 true 和 false 的实现,这些实现在其他地方实现。

当模板化参数是类型并且仅限于特定子集时,也可以执行此操作。

在编译单元中,您可以定义模板实现,然后使用与上述相同的方法再次实例化模板,但没有"extern"一词。

我已经在生产代码中执行此操作,在这种情况下,您正在创建一个成员函数来为数据库存储过程调用设置参数值,其中只允许非常有限的参数类型子集。如果您的类型是一个非常有限的子集,那么如果这有助于解耦代码并隐藏许多实现细节,请继续执行相同的操作(在随后在数据库中完成实现的情况下,这是非常值得的)。

有一个"中间"的基础,您可以在另一个标头中提供实现,我经常看到此约定的_i.h或类似内容,然后您将模板实例化为模板,仅在必要时包含此标头。因此,如果你创建一个类Foo,那么在标头中使用我的foo类的"extern"声明,在Foo.hFoo.cpp中,#include _i.h文件来实现和实例化。

至于语法,在模板实现文件中使用:

template<class Loc, class T>
LocTree<Loc,T>::method(...)
{
  ...
}