C++ 与模板类交朋友:编译错误

C++ 与模板类交朋友:编译错误,c++,templates,compiler-errors,friend,C++,Templates,Compiler Errors,Friend,我试图使用“指向实现的指针”习惯用法来隐藏我使用的是Concurrency::unbounded_缓冲区(来自VC++2010)。问题是,我在使用模板进行操作时遇到了一个编译错误。代码如下: 阻塞队列 #pragma once namespace DRA{ namespace CommonCpp{ //Forward declaration template <class Element> class BlockingQueueImpl; template

我试图使用“指向实现的指针”习惯用法来隐藏我使用的是Concurrency::unbounded_缓冲区(来自VC++2010)。问题是,我在使用模板进行操作时遇到了一个编译错误。代码如下:

阻塞队列

#pragma once

namespace DRA{
namespace CommonCpp{
    //Forward declaration
    template <class Element> class BlockingQueueImpl;

    template <class Element>
    class BlockingQueue{
        BlockingQueueImpl<Element>* m_pImpl;
    //Forbid copy and assignment
        BlockingQueue( const BlockingQueue& );
        BlockingQueue& operator=( const BlockingQueue& );
    public:
        BlockingQueue();
        ~BlockingQueue();
        void Push( Element newElement );
        Element Pop();
    };
}
}

我尝试在friend声明中将类添加到template参数中,但没有成功

模板的问题是它们只是标题。您不能将模板实现放在cpp文件中,因为整个模板在实例化时都需要可用


我怀疑你是否能在模板中使用这个习惯用法。

你的问题是模板函数定义的语法不正确。应删除第二个
关键字

template<class Element>
void BlockingQueueImpl< /*class*/ Element>::Push( Element newElement ){
    send( m_Queue, newElement );
}
模板
void BlockingQueueImpl::推送(Element newElement){
发送(m_队列,新元素);
}

是的,您不应该将模板声明和它的实现分开。

模板基本上给编译器一个模板来构造代码。它不是“真正的”代码,因为它可以按原样使用和编译。
这意味着,当您实例化一个模板(使用具有具体类类型的类或模板化方法)时,编译器需要查看实际的模板代码以生成正确的代码


所有这些基本上都意味着模板代码必须位于标题中,并包含在使用模板代码的任何其他文件中。

除了现有答案之外:

error C2649: 'typename' : is not a 'class'
我收到了相同的错误消息,但我的代码看起来略有不同:

template< class T, class TNodeType = SimpleTreeNode<T> ...>
class Tree {
    friend class TNodeType; // *** Turns out: WRONG friend declaration
template
类树{
friend类TNodeType;//***结果是:错误的friend声明
这与:Leave out class关键字中的情况相同(编译器已经知道它是我假定的类型):

template
类树{
friend TNodeType;//***确定:注意缺少'class'关键字

请注意,虽然一些编译器事先支持此格式,但它已正式成为C++11语言的一部分。此格式将被解析为
friend简单类型说明符;
用于类类型(类、结构、联合、忽略cv限定符)或者
friend typename说明符;
对于非类类型,将
simple type说明符
声明为friend(但如果尚未遇到它,则不会向前声明),或者忽略
typename说明符
,因为它不是类。它可以很好地处理模板类型参数。
BlockingQueueImpl.cpp(12): error C2649: 'typename' : is not a 'class'
template<class Element>
void BlockingQueueImpl< /*class*/ Element>::Push( Element newElement ){
    send( m_Queue, newElement );
}
error C2649: 'typename' : is not a 'class'
template< class T, class TNodeType = SimpleTreeNode<T> ...>
class Tree {
    friend class TNodeType; // *** Turns out: WRONG friend declaration
template< class T, class TNodeType = SimpleTreeNode<T> ...>
class Tree {
    friend TNodeType; // *** OK: note missing `class`keyword