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 ]