带有STL容器成员的模板类

时间:2012-04-17 08:03:06

标签: c++ templates stl visual-studio-2005

我正在编写一个模板类,它使用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 8\vc\include\utility     53
Error     2     error C2079: 'std::pair<_Ty1,_Ty2>::second' uses undefined class 'T'     c:\program files (x86)\microsoft visual studio 8\vc\include\utility     54

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

3 个答案:

答案 0 :(得分:4)

您的构造函数定义应为:

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

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

答案 1 :(得分:3)

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

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

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

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

其次,在定义类模板的成员函数之外时 class,语法是:

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

换句话说,您必须重复template<...>子句。 (是否 您在typename中使用class<...>是无关紧要的。既然如此 不必是一个班级,我认识的大多数人更喜欢typename,因为 这更接近于意思。)

至于保持实现分离:C ++中的模板是 在这方面有点破裂。你无法避免编译器 依赖。您仍然希望将实现分开 但是,定义。通常的技术是放模板 在单独的文件(例如.tcc)中实现,并包含 这来自标题。

答案 2 :(得分:2)

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

一般情况下无法完成。也就是说,在模板化参数可能是“任何”的情况下无法完成。

对于模板化参数的特定有限子集,可以执行此操作,例如,如果您有以下模板:

template< bool B > class Foo;

然后您可以指定:

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

这称为“实例化”模板,并指定编译器在其他地方实现了值true和false的实现。

这也可以在模板化参数是类型且限于特定子集的情况下完成。

在编译单元中,然后定义模板实现,然后使用与上面相同的方法再次实例化模板,但不使用“extern”一词。

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

有一个“中间”基础,你在另一个标题中提供实现,通常我已经看到_i.h或类似的约定,然后你实例化模板,包括这个标题只在必要时。因此,如果你创建一个类Foo,那么在标题中使用我的foo类的“extern”声明Foo.hFoo.cpp#include _i.h文件来实现和实例化。

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

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