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

发布于 2024-11-19 06:24:20 字数 2778 浏览 6 评论 0原文

我试图使用指向实现惯用语的指针来隐藏我正在使用 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'

我尝试将类添加到友元声明中的模板参数中,但它不起作用

I'm trying to use the Pointer to Implementation Idiom to hide the fact that I am using a Concurrency::unbounded_buffer (from VC++ 2010). The problem is, I'm doing it with templates and got stuck in a compile error. Here's the code:

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

The error is:

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

I tried adding class to the template parameter in the friend declaration, but it didn't work

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

淡淡の花香 2024-11-26 06:24:20

除了现有答案之外:

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

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

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

这与现有答案中的情况相同:省略 class 关键字(编译器已经知道这是我假设的类型):

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

Addition to existing answer:

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

I had the same error message, but my code looked slightly different:

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

The same applies as in existing answer: Leave out class keyword (compiler already knows it's a type I'd assume):

template< class T, class TNodeType = SimpleTreeNode<T> ...>
class Tree {
    friend TNodeType; // *** OK: note missing `class`keyword
聊慰 2024-11-26 06:24:20

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

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

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

Your problem is incorrect syntax of the template function definition. The second class keyword should be removed.

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

And yes, you should not separate template declaration and its implementation.

毁虫ゝ 2024-11-26 06:24:20

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

我怀疑您是否可以在模板中使用这个习惯用法。

The thing with templates is that they are header-only. You can't put template implementations in the cpp files because the entire template needs to be available when it is instantiated.

I doubt you can use this idiom with templates at all.

怪我闹别瞎闹 2024-11-26 06:24:20

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

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

templates basically give a compiler a template to construct a code. It's not "real" code in the sense that it can be used and compiled as it.
This means that when you instantiate a template (use the class or templated method somewhere with a concrete class type) the compiler needs to see the actual template code to generate the right code.

What all this basically means is that the templated code MUST be in the headers, and included to any other file that uses the templated code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文