Почему определение boost :: shared_ptr для шаблонного поведения ведет себя иначе, чем boost :: shared_ptr для не шаблонного класса? - PullRequest
1 голос
/ 23 января 2012

Я пытался интегрировать boost :: share_ptr в пару шаблонных классов, которые были первоначально получены из примера boost :: asio, который я нашел. Когда я определяю тип внутри одного класса, который является shared :: ptr этого класса. Я не могу ссылаться на тип в другом шаблонном классе. Если я удаляю шаблоны из кода, все это компилируется.

Это не скомпилируется:

#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

using namespace std;

template <typename TSomething1>
class SomeTemplateT : public boost::enable_shared_from_this<SomeTemplateT<TSomething1> >
{
public:
    typedef boost::shared_ptr<SomeTemplateT<TSomething1> > Ptr;

    static Ptr Create()
    {
        return Ptr(new SomeTemplateT<TSomething1>());
    }

    SomeTemplateT()
    {
        cout << "SomeTemplateT created" << endl;
    }
};

template <typename TSomething>
class OtherTemplateT
{
public:
    OtherTemplateT()
    {
        // COMPILATION ERROR HERE
        SomeTemplateT<TSomething>::Ptr someTemplate = SomeTemplateT<TSomething>::Create(); 
    }

private:

};

Приведенный выше код приводит к следующей ошибке компиляции:

src\Templates\main.cpp: In constructor 'OtherTemplateT<TSomething>::OtherTemplateT()':
src\comps\oamp\src\Templates\main.cpp:30: error: expected ';' before 'someTemplate'

Принимая практически один и тот же код без шаблонов, без труда компилирует:

class SomeTemplateT : public boost::enable_shared_from_this<SomeTemplateT>
{
public:
    typedef boost::shared_ptr<SomeTemplateT> Ptr;

    static Ptr Create()
    {
        return Ptr(new SomeTemplateT());
    }

    SomeTemplateT()
    {
        cout << "SomeTemplateT created" << endl;
    }
};

class OtherTemplateT
{
public:
    OtherTemplateT()
    {
        SomeTemplateT::Ptr someTemplate = SomeTemplateT::Create();
    }

private:

};

Информация о платформе: Я использую gcc4.4.0 из MinGW на Windows XP (код: Blocks IDE).

Я что-то не так делаю?

EDIT: Я забыл упомянуть, что если я заменю использование определения типа Ptr полным объявлением общего ptr: повышение :: shared_ptr Все хорошо компилируется.

Кроме того, я могу использовать тип в коде вне шаблона.

Ответы [ 3 ]

4 голосов
/ 23 января 2012

SomeTemplateT<TSomething>::Ptr является зависимым именем ;то есть его определение зависит от параметра шаблона.Компилятор не может предположить, что это имя типа, если вы не скажете так:

typename SomeTemplateT<TSomething>::Ptr someTemplate = SomeTemplateT<TSomething>::Create();
^^^^^^^^
3 голосов
/ 23 января 2012

Вам нужно использовать typename:

typename SomeTemplateT<TSomething>::Ptr someTemplate = SomeTemplateT<TSomething>::Create();

Это необходимо для возможности синтаксического анализа без семантического анализа. Является ли SomeTemplateT<TSomething>::Ptr типом или членом, неизвестно, пока SomeTemplateT<TSomething> не будет скомпилировано.

1 голос
/ 23 января 2012

Пример, взятый из стандарта C ++ 11 (n3290), который демонстрирует, почему полезно ключевое слово typename (в этом контексте). (14.6 Разрешение имен [temp.res])

struct A 
{
    struct X { };
    int X;
};

struct B 
{
    struct X { };
};

template<class T> void f(T t) 
{
    typename T::X x;
}

void foo() 
{
    A a;
    B b;
    f(b); // OK: T::X refers to B::X
    f(a); // error: T::X refers to the data member A::X not the struct A::X
}
...