我试图将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的 一切都很好。
另外,我可以在模板之外的代码中使用类型。
答案 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
}