Topic: nested template specialisation


Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Wed, 25 Oct 2006 12:17:47 CST
Raw View
paterson_andy@yahoo.co.uk wrote:
>> Thanks for that - very helpful. One more question, though: What if the
> specialisation of B requires a template parameter from A (which is what
> I wanted to express in my example, but singularly failed to do so :). I
> guess an example of this would be an "IsSameType<A,B>" template.
> Without partial specialisation, or the non-standard nested class
> specialisation, one must do something like
>
> template <typename T> yes CheckType(T*,T*);
> no CheckType(...);
>
> template <typename A,typename B>
> struct IsSameType
> {
>   enum { kResult = sizeof( CheckType( (A*)0,(B*)0) ) )  == sizeof( yes
> ) };
> };

The nested B class template effectively has two type parameters: one
provided explicitly by the client, and another, implicit parameter -
supplied by its enclosing class template. So to declare an equivalent B
class template without nesting it inside A's declaration - the only
change that should be necessary is to turn B's previously implicit A
specialization type parameter into an explicit and required type
parameter for the transplanted B class template:

    // Declared - not defined
    template <class T1, class T2>
    struct B;

    // B requires an A specialization type parameter

    template <class T1, class T2>
    struct B<A<T1>, T2>
    {
    };

    // Specialization whenever A and B have the
    // same parameterized type

    template <class T>
    struct B <A<T>, T>
    {
        void f() {}
    };

    int main()
    {
       B<int, int> b1; // Error
       B<A<int>, int> b2; // OK

       b2.f();
    }

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: paterson_andy@yahoo.co.uk
Date: Tue, 24 Oct 2006 11:27:44 CST
Raw View
Hi all,

I have a question about the correct form to use when specialising a
nested template. What I want to express is something like the
following, which is fine for some compilers, but is not standards
compliant (specialisations must occur in namespaces, or something):

template <typename T1>
struct A
{
   template < typename T2 >
   struct B
   {
   };

   // ERROR! ERROR!
   template < >
   struct B< int >
   {
   };
};

Is there any way around this?

Thanks,
AP

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Tue, 24 Oct 2006 16:06:19 CST
Raw View
paterson_andy@yahoo.co.uk wrote:
> I have a question about the correct form to use when specialising a
> nested template. What I want to express is something like the
> following, which is fine for some compilers, but is not standards
> compliant (specialisations must occur in namespaces, or something):
>
> template <typename T1>
> struct A
> {
>    template < typename T2 >
>    struct B
>    {
>    };
>
>    // ERROR! ERROR!
>    template < >
>    struct B< int >
>    {
>    };
> };
>
> Is there any way around this?

The actual problem is that the nested class B cannot be explicitly
specialized unless its enclosing calss templates are specialized as
well. So one obvious solution would be to move B's declaration outside
of A and then specify B's parameterized type when instantiating A:

    template <class T>
    struct B
    {
    };

    template <>
    struct B<int>
    {
    };

    template <class T1, class T2>
    struct A
    {
        ...
        B<T2> b;
    };

Alternately, the program can synthesize the desired behavior with a
combination of partial specialization and default template type
parameters:

    template <class T1>
    struct A
    {
       template < class T2, class T3 = T1>
       struct B
       {
       };

       template <class T4>
       struct B< int, T4>
       {
            void f() {}
       };

    };

    int main()
    {
        A<char>::B<int> b;
        b.f();
    }

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: paterson_andy@yahoo.co.uk
Date: Tue, 24 Oct 2006 21:39:46 CST
Raw View
===================================== MODERATOR'S COMMENT:
 Please do quote relevant context when replying, though this post
has not.


===================================== END OF MODERATOR'S COMMENT
Hi Greg,

Thanks for that - very helpful. One more question, though: What if the
specialisation of B requires a template parameter from A (which is what
I wanted to express in my example, but singularly failed to do so :). I
guess an example of this would be an "IsSameType<A,B>" template.
Without partial specialisation, or the non-standard nested class
specialisation, one must do something like

template <typename T> yes CheckType(T*,T*);
no CheckType(...);

template <typename A,typename B>
struct IsSameType
{
  enum { kResult = sizeof( CheckType( (A*)0,(B*)0) ) )  == sizeof( yes
) };
};

(if memory serves, boost does something like this).

My problem is that I have now come to convert an existing codebase from
one compiler, to a more standards-compliant compiler, and I'm not sure
that tricks like this will suffice in all the cases in which the
non-standard nested class specialisation is used.

The more I read on this issue, the less likely it seems that there is a
general workable solution that does not require partial specialisation.

Thanks again,
AP

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]