0

I'm writing a template class that uses a std::multimap as a member, and getting compile errors.

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()
{
}

The compile error (from 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

I know I could put the function definitions in the .h but I'm hoping to keep them separate, if it's legal to do so. How do I fix this (probably newbie) problem?

4

3 回答 3

4

Your constructor definition should be:

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

Also, hoping to keep them separate... - don't - you're wasting your time. The only way to keep them separate is to have a definition in a different header which you also include. So, technically, they are separate, but the implementation is still visible.

于 2012-04-17T08:04:56.157 回答
3

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

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<...>子句。(无论你使用typename还是classin<...>都无所谓。因为它不必是一个类,我认识的大多数人都喜欢typename,因为这更接近于它的意思。)

至于保持实现分离:C++ 中的模板在这方面有些破损。您无法避免编译器依赖性。但是,您仍然希望将实现与定义分开。通常的技术是将模板实现放在一个单独的文件中(.tcc例如),并从头文件中包含它。

于 2012-04-17T08:43:00.640 回答
2

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

一般是做不到的。也就是说,它不能在模板化参数可能是“任何东西”的情况下完成。

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

template< bool B > class Foo;

然后您可以指定:

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

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

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

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

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

有一个“中间”的地方,你在另一个头文件中提供实现,我经常看到_i.h或类似的约定,然后你实例化模板,仅在必要时包括这个头文件。因此,如果您创建一个类 Foo 然后在标题中使用我的 foo 类 inFoo.h和 in的“extern”声明Foo.cpp,用于实现和实例化#include的文件。_i.h

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

template<class Loc, class T>
LocTree<Loc,T>::method(...)
{
  ...
}
于 2012-04-17T08:23:17.877 回答