Befriend Template Class: Compilation Error
I am trying to use a pointer to an Idiom implementation to hide the fact that I am using Concurrency :: unbounded_buffer (from VC ++ 2010). The problem is I am doing this with templates and is stuck with a compilation 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 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 );
}
Mistake:
BlockingQueueImpl.cpp(12): error C2649: 'typename' : is not a 'class'
I tried adding class to template parameter in friend declaration but it didn't work
source to share
Your problem is the wrong syntax of the template function definition. The second keyword class
should be removed.
template<class Element>
void BlockingQueueImpl< /*class*/ Element>::Push( Element newElement ){
send( m_Queue, newElement );
}
And yes, you don't have to separate the template declaration and its implementation.
source to share
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
Same as in the existing answer : keep the class keyword (the compiler already knows which type I would guess):
template< class T, class TNodeType = SimpleTreeNode<T> ...>
class Tree {
friend TNodeType; // *** OK: note missing `class`keyword
source to share
templates basically give the compiler a template for building code. This is not "real" code in the sense that it can be used and compiled like it. This means that when instantiating the template (use a class or template method somewhere with a specific class type), the compiler must see the actual template code in order to generate the correct code.
What all this basically means is that the boilerplate MUST be in the headers and included in any other file that uses the boilerplate.
source to share