lundi 5 septembre 2016

Why can't I use alias from a base class in a derived class with templates?

Consider this C++ code :

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

As you can see, there are some strange (to me at least) things happening here...

First, why isn't Session_ptr accessible in the child classes ? I know because these are templated class, that make things more complicated... But I don't see any ambiguity here that makes the use of typename mandatory...

Then, why in the main, Session_ptr is accessible either as member of the base class either as member of a child class ?

Aucun commentaire:

Enregistrer un commentaire