为什么不能在带有模板的派生类中使用基类的别名?

hl0*_*37_ 3 c++ templates c++11 type-alias

考虑以下C ++代码:

template<typename Session>
class Step
{
public:
   using Session_ptr = boost::shared_ptr<Session>;
protected:
   Session_ptr m_session;
public:
   inline Step(Session_ptr session) : 
      m_session(session)
   {}

};

template<typename Socket>
class Session
{
public:
   Socket a;

   Session(Socket _a):
      a(_a)
   {}
};

template <typename Socket>
class StartSession : public Step<Session<Socket> >
{
protected:
   Session_ptr m_session; //Unknown type Session_ptr
public:
   inline StartSession(Session_ptr session) :
      Step<Session<Socket> >(session)
   {}

   void operator()(const boost::system::error_code& ec);
};

template <typename Socket>
class StartSession2 : public Step<Session<Socket> >
{
protected:
   typename Step<Session<Socket> >::Session_ptr m_session;
public:
   inline StartSession2(typename Step<Session<Socket> >::Session_ptr session) :
      Step<Session<Socket> >(session)
   {}

   void operator()(const boost::system::error_code& ec);
};

int main(int argc, char * argv[])
{
   Step<Session<int> >::Session_ptr b(new Session<int>(5)); //no problem
   StartSession<int >::Session_ptr bb(new Session<int>(5)); //gcc ok, clang refuses to remember the symbol since the class has errors
   StartSession2<int >::Session_ptr bbb(new Session<int>(5)); //no problem
   std::cout << b->a; // ok
   std::cout << bb->a; // gcc ok, clang bb not declared
   std::cout << bbb->a; // ok
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

如您所见,这里发生了一些奇怪的事情(至少对我来说)...

首先,为什么Session_ptr子类无法访问?我知道,因为这些是模板化的类,这会使事情变得更复杂...但是我在这里看不到任何使用typename强制性的歧义...

然后,为什么在主目录中Session_ptr既可以作为基类的成员又可以作为子类的成员进行访问?

Bar*_*rry 6

不合格的查找不在类模板的依赖基类中查找。

所以在这里:

template <typename Socket>
class StartSession : public Step<Session<Socket> >
{
protected:
   Session_ptr m_session; // <== unqualified name lookup on Session_ptr
   // ...
};
Run Code Online (Sandbox Code Playgroud)

Step<Session<Socket>>是的依赖基类StartSession<Socket>。为了在那里查找,您必须进行限定的名称查找(这是您在中执行的操作StartSession2):

template <typename Socket>
class StartSession : public Step<Session<Socket> >
{
protected:
   typename Step<Session<Socket>>::Session_ptr m_session;
   // ...
};
Run Code Online (Sandbox Code Playgroud)

或者直接自己添加别名:

using Session_ptr = typename Step<Session<Socket>>::Session_ptr;
Run Code Online (Sandbox Code Playgroud)

  • 不太为人所知的是,您可以使用 **派生** 类(模板)名称进行限定查找,这可以避免重复基类的模板参数:`typename StartSession::Session_ptr`。 (2认同)