Подружиться с шаблоном класса: ошибка компиляции - PullRequest
2 голосов
/ 08 июля 2011

Я пытаюсь использовать указатель на реализацию идиома, чтобы скрыть тот факт, что я использую 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'

Я попытался добавить класс к параметру шаблона в объявлении друга, но это не сработало

Ответы [ 4 ]

4 голосов
/ 09 марта 2016

Дополнение к существующему ответу:

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

У меня было то же сообщение об ошибке, но мой код выглядел немного иначе:

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

То же самое относится к существующему ответу : опустить ключевое слово класса (компилятор уже знает, что это тип, который я бы предположил):

template< class T, class TNodeType = SimpleTreeNode<T> ...>
class Tree {
    friend TNodeType; // *** OK: note missing `class`keyword
3 голосов
/ 08 июля 2011

Ваша проблема в неправильном синтаксисе определения функции шаблона.Второе ключевое слово class должно быть удалено.

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

И да, вы не должны разделять объявление шаблона и его реализацию.

1 голос
/ 08 июля 2011

шаблоны в основном дают компилятору шаблон для построения кода. Это не «настоящий» код в том смысле, что его можно использовать и компилировать как есть.
Это означает, что когда вы создаете экземпляр шаблона (где-то используется класс или шаблонный метод с конкретным типом класса), компилятор должен видеть фактический код шаблона для генерации правильного кода.

Что все это в основном означает, что шаблонный код ДОЛЖЕН быть в заголовках и включен в любой другой файл, который использует шаблонный код.

1 голос
/ 08 июля 2011

С шаблонами дело в том, что они предназначены только для заголовков. Вы не можете поместить реализации шаблонов в файлы cpp, потому что весь шаблон должен быть доступен, когда он создается.

Я сомневаюсь, что вы вообще можете использовать эту идиому с шаблонами.

...