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

+2


source to share


4 answers


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.

+3


source


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

      

+2


source


The thing with templates is that they are for headers only. You cannot put template implementations in cpp files because the entire template must be available when you create it.

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

+1


source


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.

+1


source







All Articles