为什么定义模板化的boost :: shared_ptr的行为与非模板化类的boost :: shared_ptr不同

时间:2012-01-23 15:36:02

标签: c++ templates boost compiler-errors shared-ptr

我试图将boost :: share_ptr集成到一对模板化的类中,这些类最初是从我发现的boost :: asio示例派生的。当我在一个类中定义一个类型时,该类是该类的共享:: 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:

};

平台信息: 我在Windows XP上使用MinGW的gcc4.4.0(代码:Blocks IDE)。

我做错了吗?

编辑: 我忘了提到如果我用共享ptr的完整声明替换Ptr typedef的使用:     提高:: shared_ptr的 一切都很好。

另外,我可以在模板之外的代码中使用类型。

3 个答案:

答案 0 :(得分:4)

SomeTemplateT<TSomething>::Ptr依赖名称;也就是说,它的定义取决于模板参数。除非您这样说,否则编译器不能假定它是类型名称:

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

答案 1 :(得分:3)

您需要使用typename

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

这是在没有语义分析的情况下进行解析所必需的。在编译SomeTemplateT<TSomething>::Ptr之前,SomeTemplateT<TSomething>是一个类型还是一个成员是不可知的。

答案 2 :(得分:1)

从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
}