【问题标题】:Befriending a template class: Compile error成为模板类的朋友:编译错误
【发布时间】:2011-10-01 09:13:55
【问题描述】:

我正在尝试使用指向实现习语的指针来隐藏我正在使用 Concurrency::unbounded_buffer 的事实(来自 VC++ 2010)。问题是,我正在使用模板进行操作并陷入编译错误。代码如下:

BlockingQueue.h

#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();
    };
}
}

BlockingQueue.cpp

#include "BlockingQueue.h"
#include "BlockingQueueImpl.h"

using namespace DRA::CommonCpp;

BlockingQueue<class Element>::BlockingQueue():
    m_pImpl( new BlockingQueueImpl<Element>() ){
}

BlockingQueue<class Element>::~BlockingQueue(){
    //Let the implementation's destructor handle pending Pops
    delete m_pImpl;
}

template<class Element>
void BlockingQueue<Element>::Push( Element newElement ){
    m_pImpl->Push( newElement );
}

template<class Element>
Element BlockingQueue<Element>::Pop(){
    return m_Impl->Pop();
}

BlockingQueueImpl.h

#pragma once

#include <agents.h> //This is VS2010 Exclusive (Concurrency Runtime)

namespace DRA{ namespace CommonCpp{ template <class Element> class BlockingQueue; } }

namespace DRA{
namespace CommonCpp{
template <class Element>
    class BlockingQueueImpl{
        Concurrency::unbounded_buffer<Element>  m_Queue;
    //Only friends can use this class
        friend class BlockingQueue<Element>;
        BlockingQueueImpl();
        ~BlockingQueueImpl();
    //Forbid copy and assignment
        BlockingQueueImpl( const BlockingQueueImpl& );
        BlockingQueueImpl& operator=( const BlockingQueueImpl& );
    //Members
        void Push( Element newElement );
        Element Pop();
};
}
}

BlockingQueueImpl.cpp

#include "BlockingQueueImpl.h"

using namespace DRA::CommonCpp;

BlockingQueueImpl<class Element>::BlockingQueueImpl(){
}

BlockingQueueImpl<class Element>::~BlockingQueueImpl(){
}

template<class Element>
void BlockingQueueImpl<class Element>::Push( Element newElement ){
    send( m_Queue, newElement );
}

template<class Element>
Element BlockingQueueImpl<class Element>::Pop(){
    return receive( m_Queue );
}

错误是:

BlockingQueueImpl.cpp(12): error C2649: 'typename' : is not a 'class'

我尝试在朋友声明的模板参数中添加类,但没有成功

【问题讨论】:

    标签: c++ templates compiler-errors friend


    【解决方案1】:

    现有答案的补充:

    error C2649: 'typename' : is not a 'class'
    

    我收到了相同的错误消息,但我的代码看起来略有不同:

    template< class T, class TNodeType = SimpleTreeNode<T> ...>
    class Tree {
        friend class TNodeType; // *** Turns out: WRONG friend declaration
    

    这同样适用于existing answer:省略 class 关键字(编译器已经知道这是我假设的类型):

    template< class T, class TNodeType = SimpleTreeNode<T> ...>
    class Tree {
        friend TNodeType; // *** OK: note missing `class`keyword
    

    【讨论】:

    • 请注意,虽然一些编译器预先支持这一点,但它正式成为 C++11 语言的一部分。这种格式将被解析为 friend simple-type-specifier; 用于类类型(类、结构、联合、忽略 cv 限定符)或 friend typename-specifier; 用于非类类型,声明 simple-type-specifier 成为朋友(但不会如果还没有遇到,则向前声明它),或者忽略typename-specifier,因为它不是一个类。它与模板类型参数配合得特别好。
    【解决方案2】:

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

    template<class Element>
    void BlockingQueueImpl< /*class*/ Element>::Push( Element newElement ){
        send( m_Queue, newElement );
    }
    

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

    【讨论】:

      【解决方案3】:

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

      我怀疑你是否可以在模板中使用这个习语。

      【讨论】:

        【解决方案4】:

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

        这基本上意味着模板化代码必须在标头中,并包含在使用模板化代码的任何其他文件中。

        【讨论】:

          猜你喜欢
          • 2021-12-05
          • 1970-01-01
          • 1970-01-01
          • 2017-08-08
          • 2012-03-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-29
          相关资源
          最近更新 更多