CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    Feb 2011
    Posts
    4

    templates, typedefs and inheritance

    I find templates and inheritance confusing, something about qualified/unqualified lookups. Mostly I manage, but here is something that's troubling me:

    I have base classes that depend on template parameters, and that contain convenient typedef's that may or may not also depend on the template parameters. When I inherit from the base classes, the typedefs are generally _not_ visible. Since I don't want to type e.g.

    BaseClass<typename1, typename2>::mytypedef

    (or worse) for every "mytypedef", I make a new typedef

    typedef BaseClass<typename1, typename2>::mytypedef mytypedef;

    in the derived class. Obviously this works, but it feels a bit dirty. The problem now is that I'm starting to use Doxygen and Doxygen dutifully reports all the different typedefs, which looks ugly. With variables I can do e.g.

    using BaseClass<typename1, typename2>::myvar

    in the derived class. Can you do something similar with typedef's instead of declaring new ones all the time?

  2. #2
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: templates, typedefs and inheritance

    Declaring the template parameters in the typedef is not necessary.

    Code:
    template <typename T>
    class X
    {
    public:
        typedef unsigned int UI;
    };
    
    
    class Y : public X<int>
    {
    public:
        typedef X::UI UI; // No template parameters are required for X.
    };
    
    int main()
    {
        Y::UI ui;
    }
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  3. #3
    Join Date
    Apr 2008
    Posts
    725

    Re: templates, typedefs and inheritance

    Code:
    template<class T>
    class B
    {
    public:
    	virtual T foo(T var)
    	{
    		return var;
    	}
    
      typedef T value_type;
    };
    
    template<class T>
    class D : public B<T>
    {
    public:
    };
    
    
    int main( void )
    {
      B<int> bb;
      B<int>::value_type i = bb.foo(6);
    
      D<char> dd;
      D<char>::value_type c = dd.foo('a');
    
    	return 0;
    }

  4. #4
    Join Date
    Aug 2006
    Location
    Timisoara, Romania
    Posts
    433

    Re: templates, typedefs and inheritance

    Quote Originally Posted by odinlake
    I have base classes that depend on template parameters, and that contain convenient typedef's that may or may not also depend on the template parameters. When I inherit from the base classes, the typedefs are generally _not_ visible.
    the idea is that you have to declare your types ("mytypedef") as public in the "base" class so that you can access that type using the "derived" class. and don't forget that the derived class should inherit as public from the base class (i.e. "class derived: public base {...};"). That is, you need to inherit as public if you want to use your type outside your object (e.g. in main() ) or as public or protected if you have another class (e.g. called derived2) that inherits from your "derived".
    Last edited by Feoggou; February 16th, 2011 at 02:52 PM.

  5. #5
    Join Date
    Feb 2011
    Posts
    4

    Re: templates, typedefs and inheritance

    Thanks for trying to help but.. JohnW@Wessex, from your code with gcc 4.4.5 I get

    Code:
    tdtest.cc:70: error: ‘template<class T> class X’ used without template parameters
    tdtest.cc:70: error: ISO C++ forbids declaration of ‘UI’ with no type
    tdtest.cc:70: error: typedef name may not be a nested-name-specifier
    tdtest.cc:70: error: expected ‘;’ before ‘UI’
    Amleto, thanks (I learned something). A clarification of my situation though:

    Code:
    template<class T>
    class B
    {
    public:
    	virtual T foo(T var)
    	{
    		return var;
    	}
    
      typedef T value_type;
    };
    
    
    template<class T>
    class D : public B<T>
    {
    public:
      typedef typename B<T>::value_type value_type;
    
      virtual T foo(T var)
      {
        value_type nvar = var;
        return nvar;
      }
    };
    
    
    int main( void )
    {
      B<int> bb;
      B<int>::value_type i = bb.foo(6);
    
      D<char> dd;
      D<char>::value_type c = dd.foo('a');
    
      return 0;
    }
    It seems messy (and messes up Doxygen) that I should need the line

    Code:
      typedef typename B<T>::value_type value_type;
    But as far as I've seen the only alternative would be to use B<T>::value_type everywhere instead of just value_type. Although B<T> is short here, these things can easily become ridiculously long, like

    Code:
      SomeDescripriveClassName< AnotherClassName<typea, typeb>::typec, YetAnotherClassName<typed>::typee >::mytype;
    but if there is no pretty alternative than there isn't and I should just stop asking for it.

  6. #6
    Join Date
    Apr 1999
    Posts
    27,449

    Re: templates, typedefs and inheritance

    Quote Originally Posted by odinlake View Post
    Thanks for trying to help but.. JohnW@Wessex, from your code with gcc 4.4.5 I get

    Code:
    tdtest.cc:70: error: ‘template<class T> class X’ used without template parameters
    tdtest.cc:70: error: ISO C++ forbids declaration of ‘UI’ with no type
    tdtest.cc:70: error: typedef name may not be a nested-name-specifier
    tdtest.cc:70: error: expected ‘;’ before ‘UI’
    JohnW's code compiles without error using the Comeau C++ on-line compiler, which is one of, if not, the most ANSI C++ compliant compilers around.

    Regards,

    Paul McKenzie

  7. #7
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: templates, typedefs and inheritance

    Quote Originally Posted by Paul McKenzie View Post
    JohnW's code compiles without error using the Comeau C++ on-line compiler,
    I often check there before posting, just in case my example only works in V.S.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  8. #8
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: templates, typedefs and inheritance

    Quote Originally Posted by odinlake View Post
    Thanks for trying to help but.. JohnW@Wessex, from your code with gcc 4.4.5 I get ...
    The difference between your code and mine is that, in mine, the value type is independent of T, whilst in yours it is dependent.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  9. #9
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: templates, typedefs and inheritance

    Quote Originally Posted by odinlake View Post
    I have base classes that depend on template parameters, and that contain convenient typedef's that may or may not also depend on the template parameters. When I inherit from the base classes, the typedefs are generally _not_ visible.
    Please show the definition of your base class including these typedefs. You must have done something wrong, because if this really isn't possible in your compiler, then most of the classes in <functional> wouldn't compile. They are derived from std::unary_function or std::binary function which does nothing more than typedef some template arguments.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  10. #10
    Join Date
    Aug 2006
    Location
    Timisoara, Romania
    Posts
    433

    Re: templates, typedefs and inheritance

    Quote Originally Posted by odinlake
    But as far as I've seen the only alternative would be to use B<T>::value_type everywhere instead of just value_type. Although B<T> is short here, these things can easily become ridiculously long, like
    Code:
    SomeDescripriveClassName< AnotherClassName<typea, typeb>::typec, YetAnotherClassName<typed>::typee >::mytype;
    well, in your code where you use it, you can use a typedef for it:
    Code:
    typedef SomeDescripriveClassName< AnotherClassName<typea, typeb>::typec, YetAnotherClassName<typed>::typee >::mytype shortType;
    or you can use more typedef-s:
    Code:
    typedef AnotherClassName<typea, typeb>::typec shortType1;
    typedef YetAnotherClassName<typed>::typee shortType2;
    typedef SomeDescripriveClassName< shortType1, shortType2 >::mytype shortType;
    so you won't have to write all that much to define a variable:
    Code:
    shortType yourVar;
    (where typea, typeb, etc. should be real types, like int, char, etc. not template type names).

    by the way, in my VS this works well:

    Code:
    template<class T>
    class B
    {
    public:
    	virtual T foo(T var)
    	{
    		return var;
    	}
    
      typedef T value_type;
    };
    
    
    template<class T>
    class D : public B<T>
    {
    public:
    //don't need the following line, because we already have "typedef T value_type;" inherited.
    //typedef typename B<T>::value_type value_type;
    
      virtual T foo(T var)
      {
    //value_type is defined as "typedef T B<T>::value_type;"
    //so this
        value_type nvar = var;
    //is the same as this:
    //  T nvar = var;
        return nvar;
      }
    };
    
    
    int main( void )
    {
      B<int> bb;
      B<int>::value_type i = bb.foo(6);
    
      D<char> dd;
      D<char>::value_type c = dd.foo('a');
    
      return 0;
    }

  11. #11
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: templates, typedefs and inheritance

    Quote Originally Posted by Feoggou View Post
    By the way, in my VS this works well:
    But not in Comeau I'm afraid.

    Code:
    "ComeauTest.c", line 25: error: identifier "value_type" is undefined
          value_type nvar = var;
          ^
    
    "ComeauTest.c", line 25: error: expected a ";" (perhaps on the previous statement)
          value_type nvar = var;
                     ^
    
    "ComeauTest.c", line 28: error: identifier "nvar" is undefined
          return nvar;
                 ^
    
    3 errors detected in the compilation of "ComeauTest.c".
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  12. #12
    Join Date
    Feb 2011
    Posts
    4

    Re: templates, typedefs and inheritance

    Aha, three different compilers with three different behaviours regarding the code posted: With GCC and Comeau typedefs depending on template parameters are not visible in the derived class, but they are with VS. With Comeau (and VS?) but not with GCC, one may omit template parameters when declaring typedefs.

    Here is a piece of code that compiles in GCC and probably in the others as well:

    Code:
    class Base0
    {
    
    public:
      typedef float atype;
      int anint;
      atype avar;  
    };
    
    
    class Derived0 : public Base0
    {
    
    public:
    
      void foo(atype in)
      {
        anint  = 0;
        avar   = in;
      }
    };
    
    
    template<typename S>
    class Base1
    {
    
    public:
      typedef S atype;
      int anint;
      atype avar;
    };
    
    
    template<typename S>
    class Derived1 : public Base1<S>
    {
    
    public:
      typedef typename Base1<S>::atype atype;
      using Base1<S>::anint;
      using Base1<S>::avar;
    
      void foo(S in)
      {
        atype tmp = in;
    
        anint  = 0;
        avar   = tmp;
      }
    };
    In GCC, to be sure, removing the typedef or using statements in Derived1 will break the code. Just to explain the reason I started the thread: It seemed intuitive to me that I should be able to do the same with the typedef as I do with the member variables, that is, write something like

    Code:
      using typename Base1<S>::atype;
    but it doesn't seem to work that way.

    Thanks for the replies.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured