【问题标题】:Why is it that defining boost::shared_ptr of a templated behaves differently than boost::shared_ptr of a non templated class为什么定义模板的 boost::shared_ptr 的行为与非模板类的 boost::shared_ptr 的行为不同
【发布时间】:2012-01-23 15:36:02
【问题描述】:

我试图将 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:

};

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

我做错了吗?

编辑: 我忘了提到,如果我用共享 ptr 的完整声明替换 Ptr typedef 的使用: boost::shared_ptr 一切编译正常。

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

【问题讨论】:

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


【解决方案1】:

SomeTemplateT&lt;TSomething&gt;::Ptr 是一个依赖名称;也就是说,它的定义取决于模板参数。除非你这么说,否则编译器不能假定它是一个类型名称:

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

【讨论】:

  • 做到了。我必须记住,每次遇到这些奇怪的错误时,请输入 typename :-)
  • @Lou:当您遇到这些错误时,实际上是可以预测的。如果类型的名称有模板参数,请使用typename
【解决方案2】:

你需要使用typename:

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

这是在没有语义分析的情况下进行解析所必需的。 SomeTemplateT&lt;TSomething&gt;::Ptr 是类型还是成员在编译 SomeTemplateT&lt;TSomething&gt; 之前是未知的。

【讨论】:

    【解决方案3】:

    取自 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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-18
      • 1970-01-01
      相关资源
      最近更新 更多