CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9
  1. #1
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Any nice way to get round the old "template typedefs are illegal" problem?

    Here's a bit of context. I have a non-template class that contains a nested template class:

    Code:
    class A
    {
    public:
      typedef size_t size_type;
    
      template <typename T>
      class N
      {
         //...
      };
      //...
    };
    The above definition is used a traits class

    Code:
    template <typename T, typename Class_>
    struct SomeTraits
    {
       typedef typename Class_::template N<T> n_type;
       typedef typename Class_::size_type size_type;
    };
    The problem is, that I also have a class B, and that class needs to contain the same nested class as class A. Ideally, what I would like to do is the following:

    Code:
    template <typename T>
    class NCommon
    {
        //...
    };
    
    class A
    {
    public:
       typedef size_t size_type;
    
       template <typename T> typedef NCommon<T> N<T>;
      
      //...
    };
    
    class B
     {
     public:
       typedef size_t size_type;
    
       template <typename T> typedef NCommon<T> N<T>;
       //...
     };
    But that typedef is illegal. The only way round the problem that I can think of is the following:

    Code:
    template <typename T>
    class NCommon
    {
         //...
    protected:
      ~NCommon(){}
    };
    
    class A
     {
     public:
       typedef size_t size_type;
    
      template <typename T> 
      class N : public NCommon
      {};
       
       //...
     };
    
    class B
      {
      public:
        typedef size_t size_type;
     
       template <typename T> 
       class N : public NCommon
       {};
        
        //...
      };
    But I would rather have a more elegant solution. Any ideas/comments welcome.

  2. #2
    Join Date
    Oct 2005
    Location
    England
    Posts
    803

    Re: Any nice way to get round the old "template typedefs are illegal" problem?

    Would declaring the template class as a friend of A and B work?

    Code:
    template <typename T>
    class NCommon
    {
         //...
    protected:
      ~NCommon(){}
    };
    
    template <typename T> 
      class N : public NCommon<T>
      {};
    
    class A
     {
     public:
       typedef size_t size_type;
    template <typename T> 
       friend class N;
    
      
       
       //...
     };
    
    class B
      {
      public:
        typedef size_t size_type;
    	template <typename T> 
    	friend class N;
    	
        
        //...
      };
    Rich

    Visual Studio 2010 Professional | Windows 7 (x64)
    Ubuntu

  3. #3
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Any nice way to get round the old "template typedefs are illegal" problem?

    That's a nice thought, but unfortunately it won't work, because the friend keyword only allows N to see the private and protected parts of classes A and B, it doesn't add N as a name within them.

    The way I see it, I have three options, the first being to duplicate the code. The second being to add T as a template parameter to the class A and class B declarations - but this not only messes up the desigh, but actually ruins the semantics of the destination code. The third being to use the inheritance mechanism suggested in my prior post - but I don't like that idea since it is clearly a code fudge. Although I don't like the idea of duplicate code, in this instance I think I'll go with the duplicate code option.

    Thanks for the suggestion though, I really appreciate it.

  4. #4
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Any nice way to get round the old "template typedefs are illegal" problem?

    why do you find your "inheritance mechanism" so bad ? (I mean, it makes sense from a design point of view)

    anyway, you could also try

    Code:
    class NCommon
    {
    public:
    	template <typename T>
    	class N
    	{
    	    //...
    	};
    };
    
    class A
    {
    public:
    	static const bool	forwarded = true;
      	typedef NCommon 	forwarder;
    };
    
    class B
    {
    public:
    	static const bool	forwarded = true;
    	typedef NCommon 	forwarder;
    };
    
    class C
    {
    public:
    	static const bool		forwarded = false;
    	template <typename T> class 	N {/*...*/};
    };
    
    template <typename T, typename Class_, bool forwarded = Class_::forwarded>
    struct SomeTraits
    {
    	typedef typename Class_::template N<T> 			n_type;
    	// typedef typename Class_::size_type 			size_type;
    };
    
    template <typename T, typename Class_>
    struct SomeTraits<T,Class_,true>
    {
    	typedef typename Class_::forwarder::template N<T> 			n_type;
    	// typedef typename Class_::forwarder::size_type 			size_type;
    };
    or a variation thereof.

  5. #5
    Join Date
    Jan 2006
    Location
    Belo Horizonte, Brazil
    Posts
    405

    Re: Any nice way to get round the old "template typedefs are illegal" problem?

    If you place a kind of self identification inside NCommon would it be a solution for you?

    Code:
    #include <cstddef>
    
    class A
    {
    public:
      typedef size_t size_type;
       
      template <typename T>
      struct NCommon
      {
        typedef NCommon<T> Self;
      };
    };
    
    class B
    {
    public:
      typedef size_t size_type;
    
      template <typename T>
      struct NCommon
      {
        typedef NCommon<T> Self;
      };
    };
    
    template <typename T, typename Class_>
    struct SomeTraits
    {
       typedef typename Class_::size_type size_type;
       typedef typename Class_::template NCommon<T>::Self N_type; 
    };
    
    int main()
    {
      SomeTraits<int, A> a;
      SomeTraits<int, B> b;
    }

  6. #6
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Any nice way to get round the old "template typedefs are illegal" problem?

    Quote Originally Posted by superbonzo View Post
    why do you find your "inheritance mechanism" so bad ? (I mean, it makes sense from a design point of view)

    anyway, you could also try

    Code:
    class NCommon
    {
    public:
        template <typename T>
        class N
        {
            //...
        };
    };
    
    class A
    {
    public:
        static const bool    forwarded = true;
          typedef NCommon     forwarder;
    };
    
    class B
    {
    public:
        static const bool    forwarded = true;
        typedef NCommon     forwarder;
    };
    
    class C
    {
    public:
        static const bool        forwarded = false;
        template <typename T> class     N {/*...*/};
    };
    
    template <typename T, typename Class_, bool forwarded = Class_::forwarded>
    struct SomeTraits
    {
        typedef typename Class_::template N<T>             n_type;
        // typedef typename Class_::size_type             size_type;
    };
    
    template <typename T, typename Class_>
    struct SomeTraits<T,Class_,true>
    {
        typedef typename Class_::forwarder::template N<T>             n_type;
        // typedef typename Class_::forwarder::size_type             size_type;
    };
    or a variation thereof.
    It's not that I find the thought of inheritance so bad, it's just I feel there has to be a better solution. I like your solution, but it adds an extra bit of indirection, that's the only qualm I have with it. Thanks for the suggestion.

  7. #7
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Any nice way to get round the old "template typedefs are illegal" problem?

    Quote Originally Posted by ltcmelo View Post
    If you place a kind of self identification inside NCommon would it be a solution for you?

    Code:
    #include <cstddef>
    
    class A
    {
    public:
      typedef size_t size_type;
       
      template <typename T>
      struct NCommon
      {
        typedef NCommon<T> Self;
      };
    };
    
    class B
    {
    public:
      typedef size_t size_type;
    
      template <typename T>
      struct NCommon
      {
        typedef NCommon<T> Self;
      };
    };
    
    template <typename T, typename Class_>
    struct SomeTraits
    {
       typedef typename Class_::size_type size_type;
       typedef typename Class_::template NCommon<T>::Self N_type; 
    };
    
    int main()
    {
      SomeTraits<int, A> a;
      SomeTraits<int, B> b;
    }
    That's an interesting idea, but it doesn't solve the problem that I wish to solve, and that is to prevent the duplication of common code, whilst keeping access to class N simple through the traits class.

  8. #8
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Any nice way to get round the old "template typedefs are illegal" problem?

    Thanks for all of your input, I have finally come to a solution - one that probably won't be obvious from my prior posts, since I didn't give you the relationship between classes A and B. The difference between class A and B, is that A specifies an interleaved data format (and how to cope with it) and B specifies a planer data format (and how to cope with it). My solution is to create a template class C with a boolean isPlaner template parameter, and also I'll define the nested class N within the template class C.

    Code:
    template <bool isPlaner>
    class C
    {
    public:
      void doSomething() const;
    
      template <typename T>
      class N
      {
         //...
      }
    };
    I'll then specialise the functions that should behave differently, in the above case that's doSomething.
    Code:
    template<>
    void C<true>::doSomething() const
    {
       //do something
    }
    
    template<>
    void C<false>::doSomething() const
    {
       //do something else
    }
    That now means that A and B can be realised through the appropriate typedefs of class C.
    Code:
    typedef C<false> A;
    typedef C<true> B;
    Thanks once again for all your input.

  9. #9
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Any nice way to get round the old "template typedefs are illegal" problem?

    ok, we were a bit out of context ! anyway, just for completeness, here is a variation of my post code using a small (but very useful) MPL facility:

    Code:
    class A
    {
    public:
        typedef unsigned int	size_type;
        template <typename T> class N {/*...*/};
    };
    
    class B
    {
    public:
        typedef A SameTraitsAs;
    };
    
    namespace detail {
    
    BOOST_MPL_HAS_XXX_TRAIT_DEF( has_SameTraitsAs );
    
    } // end - detail
    
    template <typename T, typename Class_, bool forwarded = detail::has_SameTraitsAs<Class_>::value >
    struct SomeTraits
    {
        typedef typename Class_::template N<T>         n_type;
        typedef typename Class_::size_type             size_type;
    };
    
    template <typename T, typename Class_>
    struct SomeTraits<T,Class_,true>
    {
        typedef typename Class_::SameTraitsAs::template N<T>         n_type;
        typedef typename Class_::SameTraitsAs::size_type             size_type;
    };
    usage is more expressive and less redundant in this way...

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