2011-07-08 8 views
2

私は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' 

私は友人の宣言でテンプレートパラメータにクラスを追加しようとしたが、それは、テンプレートと

答えて

3

問題は、テンプレート関数定義の構文が正しくありません。 2番目のclassキーワードは削除する必要があります。

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

はい、テンプレート宣言とその実装を分けてはいけません。

1

事を動作しませんでした彼らはヘッダーのみされていることです。 cppファイルにテンプレートの実装を置くことはできません。なぜなら、テンプレート全体がインスタンス化されるときに利用可能でなければならないからです。

テンプレートでこのイディオムを使用することはできません。

1

テンプレートは基本的にコンパイラにコードを作成するテンプレートを与えます。それは、それが使用され、コンパイルされるという意味では、「本当の」コードではありません。
これは、テンプレートをインスタンス化するとき(クラスまたはテンプレートメソッドを具体的なクラスタイプのどこかで使用するとき)、コンパイラは正しいコードを生成するために実際のテンプレートコードを参照する必要があることを意味します。

基本的には、テンプレートコードはヘッダーに含まれていなければならず、テンプレートコードを使用する他のファイルにも含まれていなければなりません。既存の答えに

2

追加:

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 
+1

一部のコンパイラ彼は事前にC++ 11の言語の一部となっていました。この形式は、クラス型(class、struct、union、cv-qualifierを無視する)、または 'friend typename-specifier;'クラスの型として 'friend simple-type-specifier;'と解釈され、 'class simple ' (まだ遭遇していない場合にはそれを宣言しません)、あるいは 'typename-specifier'を無視します。これはクラスではないからです。テンプレート型のパラメータでうまく演奏されます。 –

関連する問題