Nested template specialization?

S

stephen.diverdi

Can anyone lend a hand on getting this particular template
specialization working? I've been trying to compile with g++ 4.1 and
VS 2005.

//------------------------------------------------------------------

// my regular glass
class A { };

// my templated class
template < typename T > class B { };

// this is a library class with a library function i want to
specialize for my classes
template < typename T >
class C
{
public:
void func ( T arg )
{
fprintf( stderr, "C< T >\n" );
}
};

// specialization on A works just fine
template < >
void C< A >::func ( A arg )
{
fprintf( stderr, "C< A >\n" );
};

// specialization on B<T> fails to compile
template < typename T >
void C< B< T > >::func ( B< T > arg )
{
fprintf( stderr, "C< B< T > >\n" );
};

//------------------------------------------------------------------

The motivation for this is I have a templated class that has
particular memory allocation requirements (I need it to be aligned),
that I'd like to be able to use with STL containers without having to
pass in a custom allocator every time. So I'm trying to overload
std::allocator's allocate and deallocate member functions to work on
my template class. I'm afraid this is a funny form of partial
specialization of a function and I'm just out of luck, but maybe
there's a workaround? I'm sure other people have had similar
difficulties...Thanks,

-stephen diverdi
(e-mail address removed)
 
V

Victor Bazarov

Can anyone lend a hand on getting this particular template
specialization working? I've been trying to compile with g++ 4.1 and
VS 2005.

//------------------------------------------------------------------

// my regular glass
class A { };

// my templated class
template < typename T > class B { };

// this is a library class with a library function i want to
specialize for my classes
template < typename T >
class C
{
public:
void func ( T arg )
{
fprintf( stderr, "C< T >\n" );
}
};

// specialization on A works just fine
template < >
void C< A >::func ( A arg )
{
fprintf( stderr, "C< A >\n" );
};

// specialization on B<T> fails to compile
template < typename T >
void C< B< T > >::func ( B< T > arg )
{
fprintf( stderr, "C< B< T > >\n" );
};

//------------------------------------------------------------------

The motivation for this is I have [..valid reason..]
I'm afraid this is a funny form of partial
specialization of a function and I'm just out of luck, but maybe
there's a workaround? I'm sure other people have had similar
difficulties...Thanks,

It's not "a funny form of partial specialization of a function".
It's a prohibited attempt to specialise a member without first
specialising the class template. You need to specialise C<B<T>>
first and declare that it does have the same 'func' member.

V
 
B

Barry

Can anyone lend a hand on getting this particular template
specialization working? I've been trying to compile with g++ 4.1 and
VS 2005.

//------------------------------------------------------------------

// my regular glass
class A { };

// my templated class
template < typename T > class B { };

// this is a library class with a library function i want to
specialize for my classes
template < typename T >
class C
{
public:
void func ( T arg )
{
fprintf( stderr, "C< T >\n" );
}
};

// specialization on A works just fine
template < >
void C< A >::func ( A arg )
{
fprintf( stderr, "C< A >\n" );
};

// specialization on B<T> fails to compile
template < typename T >
void C< B< T > >::func ( B< T > arg )
{
fprintf( stderr, "C< B< T > >\n" );
};

//------------------------------------------------------------------

The motivation for this is I have a templated class that has
particular memory allocation requirements (I need it to be aligned),
that I'd like to be able to use with STL containers without having to
pass in a custom allocator every time. So I'm trying to overload
std::allocator's allocate and deallocate member functions to work on
my template class. I'm afraid this is a funny form of partial
specialization of a function and I'm just out of luck, but maybe

I guess it is.
there's a workaround? I'm sure other people have had similar

you have to partial specialize the whole class

template < typename T >
class C <B<T> >{
public:
void C< B< T > >::func ( B< T > arg )
{
fprintf( stderr, "C< B< T > >\n" );
}

};

yah, then have much more work to do with the rest of members.
 
B

Barry

Barry said:
I guess it is.


you have to partial specialize the whole class

template < typename T >
class C <B<T> >{
public:
void C< B< T > >::func ( B< T > arg )

just copy your code
should be:
 
S

stephen.diverdi

It's not "a funny form of partial specialization of a function".
It's a prohibited attempt to specialise a member without first
specialising the class template. You need to specialise C<B<T>>
first and declare that it does have the same 'func' member.
Hmm, so why don't I need to specialize C<A> first before creating
the specialized C<A>::func implementation?

And as it relates to my motivation, your answer means I'm going
to have to copy the entire implementation of std::allocator and
specialize every member functionf or C<B<T>>?

Thanks,

-stephen diverdi
(e-mail address removed)
 
V

Victor Bazarov

Hmm, so why don't I need to specialize C<A> first before creating
the specialized C<A>::func implementation?


Because with C<A>::func it's an explicit *full* specialisation,
which triggers an implicit instantiation of C said:
And as it relates to my motivation, your answer means I'm going
to have to copy the entire implementation of std::allocator and
specialize every member functionf or C<B<T>>?


Yes, if you want the precisely same layout, behaviour, etc. Of
course, you could simply extract the function in question into
a separate class and specialise only it (and then derive from it)
thus saving some typing...

V
 
S

stephen.diverdi

And as it relates to my motivation, your answer means I'm going
Yes, if you want the precisely same layout, behaviour, etc. Of
course, you could simply extract the function in question into
a separate class and specialise only it (and then derive from it)
thus saving some typing...
Hmm, I'm not sure I understand - I would definitely like to save
typing (and reduce the potential for bugs), but as I interpret what
you've suggested, I would have to change the definition of
std::allocator, which isn't really an option. The goal here is to
have my template class work seamlessly with the STL containers, and
then I will distribute my template class for others to use as part of
a library. So requiring custom STL classes isn't feasible.

I guess the problem is that C++ treats partially specialized templates
(which C<B<T>> is, correct?) as completely separate entities. On the
one hand, that's nice because it gives you complete control over how
the template (C<T>) and the partial specialization (C<B<T>>) differ,
but on the other hand, it's a serious drag on maintainability (every
partial specialization increases the work to maintain consistency
across implementations). That's too bad, because they'd really be
nice otherwise. Is there a reason partial specialization doesn't work
more like inheritence, by duplicating the members and implementations
unless the partial specialization overrides them? That seems to be
what full specialization does (i.e. the case above for C<int>::func).

-stephen diverdi
(e-mail address removed)
 
V

Victor Bazarov

Hmm, I'm not sure I understand - I would definitely like to save
typing (and reduce the potential for bugs), but as I interpret what
you've suggested, I would have to change the definition of
std::allocator, which isn't really an option. The goal here is to
have my template class work seamlessly with the STL containers, and
then I will distribute my template class for others to use as part of
a library. So requiring custom STL classes isn't feasible.

I guess the problem is that C++ treats partially specialized templates
(which C<B<T>> is, correct?) as completely separate entities. On the
one hand, that's nice because it gives you complete control over how
the template (C<T>) and the partial specialization (C<B<T>>) differ,
but on the other hand, it's a serious drag on maintainability (every
partial specialization increases the work to maintain consistency
across implementations). That's too bad, because they'd really be
nice otherwise. Is there a reason partial specialization doesn't work
more like inheritence, by duplicating the members and implementations
unless the partial specialization overrides them? That seems to be
what full specialization does (i.e. the case above for C<int>::func).

I am not sure I understand. What would drive the language creators
to specify the partial specialisation "more like" inheritance when you
can accomplish the same thing with inheritance, while NOT specifying
it "more like" inheritance actually gives you more freedom? Besides,
the biggest pitfall of allowing the partial specialisation work that
way is that any changes in the original template suddenly would be
propagated into all partially specialised ones without even a notice
or a warning.

Also, partial specialisaion is often used to change the structure and
behaviour of a template for, say, all pointers, in which case allowing
"inheritance" is more headache than gain. IMHO.

V
 
S

stephen.diverdi

I am not sure I understand. What would drive the language creators
to specify the partial specialisation "more like" inheritance when you
can accomplish the same thing with inheritance, while NOT specifying
it "more like" inheritance actually gives you more freedom?

The entire idea behind templates (unless I've misunderstood) is to
avoid
having to specify the API and implementation for separate classes that
have fundamentally the same behavior, just parameterized on a few
basic
arguments (type, int, etc.). If I want to make an array class that
operates on int's, float's, and MyClass's, without templates I have to
write all three, whereas with templates, I write once.

I expected that partial specialization would attempt to further that
same
goal, but the fact that the entire class needs to be redefined for
each
partial specialization seems to directly contradict the original goal
of templates.

In the end, writing separate classes for every case gives you the most
freedom, so why have templates at all?

And while I said "inheritance-like", clearly templates and inheritance
serve different (orthogonal?) purposes. You could not use inheritance
to, e.g., implement a class (or set of classes) that mimiced the API
behavior of STL's vector.
Besides,
the biggest pitfall of allowing the partial specialisation work that
way is that any changes in the original template suddenly would be
propagated into all partially specialised ones without even a notice
or a warning.
That's actually exactly the advantage of such an approach. If I make
a
change to my template, I don't want to have to propogate that change
into
every partial specialization manually, as that generates a lot more
work
and increases the potential for bugs.

Analogously, if you make a change to a base class, all the classes
that
inherit from it are updated without notice or warning. Do you think
that's
a bad thing?
Also, partial specialisaion is often used to change the structure and
behaviour of a template for, say, all pointers, in which case allowing
"inheritance" is more headache than gain. IMHO.
Behavior, yes, I agree. Structure? Do people use partial
specialization
to make API changes to their classes? That seems like bad practice.
How
confusing would it be to look at a template class definition,
instantiate
an object with some template arguments, and then find out it has a
totally
different API because you didn't notice that in another header there's
a
partial specialization that completely redefines it?


-stephen diverdi
(e-mail address removed)
 
V

Victor Bazarov

The entire idea behind templates (unless I've misunderstood) is to
avoid
having to specify the API and implementation for separate classes that
have fundamentally the same behavior, just parameterized on a few
basic
arguments (type, int, etc.). If I want to make an array class that
operates on int's, float's, and MyClass's, without templates I have to
write all three, whereas with templates, I write once.

I expected that partial specialization would attempt to further that
same
goal, but the fact that the entire class needs to be redefined for
each
partial specialization seems to directly contradict the original goal
of templates.

In the end, writing separate classes for every case gives you the most
freedom, so why have templates at all?

Yes, you do sound confused.

The fact that you can partially specialise a template thus extracting
a whole (usually infinite) subset of (usually infinite) specialisations
and define them differently (than the original template) does *not*
contradict the purpose of templates at all. Actually, it affirms it.

If I have to guess, it's the word "specialisation" that confuses you.
A partial specialisation is effectively a *different* template, and
the only thing that ties them together is the name, which can be used
elsewhere by somebody who doesn't want to concern himself with how
many different "specialisations" the compiler knows about.
And while I said "inheritance-like", clearly templates and inheritance
serve different (orthogonal?) purposes.
Undoubtedly.

You could not use inheritance
to, e.g., implement a class (or set of classes) that mimiced the API
behavior of STL's vector.

I am not sure how this is relevant here.
That's actually exactly the advantage of such an approach. If I make
a
change to my template, I don't want to have to propogate that change
into
every partial specialization manually, as that generates a lot more
work
and increases the potential for bugs.

Analogously, if you make a change to a base class, all the classes
that
inherit from it are updated without notice or warning. Do you think
that's
a bad thing?

No, but that's the purpose of the inheritance mechanism. Why have
two mechanisms that have exactly the same effect in the language?
That's what I mean by the freedom. The more mechanisms with different
effects you have, the more choices you have when trying to accomplish
your goal.

The effect you want is attainable using inheritance. Partial template
specialisation is *not* going to help. Why do you keep expressing
the desire to use partial specialisation to do what inheritance is
designed to do?
Behavior, yes, I agree. Structure? Do people use partial
specialization
to make API changes to their classes? That seems like bad practice.

I don't know what you're talking about, and am not going to guess.
How
confusing would it be to look at a template class definition,
instantiate
an object with some template arguments, and then find out it has a
totally
different API because you didn't notice that in another header there's
a
partial specialization that completely redefines it?

Probably not the effect you want, but if you know that that's not
desirable, don't make it so.

V
 
S

stephen.diverdi

If I have to guess, it's the word "specialisation" that confuses you.
A partial specialisation is effectively a *different* template, and
the only thing that ties them together is the name, which can be used
elsewhere by somebody who doesn't want to concern himself with how
many different "specialisations" the compiler knows about.
Please explain to me then what is the advantage of creating a partial
specialization versus creating an entirely separate template class
then?
I am not sure how this is relevant here.
I was replying to your statement in a previous post that "you can
accomplish the same thing with inheritance", which you seem to be
making again in this post. This is categorically false.
No, but that's the purpose of the inheritance mechanism. Why have
two mechanisms that have exactly the same effect in the language?
That's what I mean by the freedom. The more mechanisms with different
effects you have, the more choices you have when trying to accomplish
your goal.
Templates provide a way to parameterize aspects your class definition,
while inheritance provides a way for objects to assume the properties
of many different related types at run time. The way templates and
inheritance differ is separate from the way partial specialization is
handled, as compared to subclassing. Even if partial specialization
of templates propogated APIs the same way inheritance does, they would
still be fundamentally different constructs and would still serve
fundamentally different purposes.
The effect you want is attainable using inheritance. Partial template
specialisation is *not* going to help. Why do you keep expressing
the desire to use partial specialisation to do what inheritance is
designed to do?
Please propose a way create a set of vector classes using
inheritance. I would like one class for each combination of
{int,float,double} and {2,3,4}-dimensions. They should all have the
same API, though the implementations for the different dimensions will
differ (for performance reasons). I would also like compile-time
typechecking and conversion for operations among these types.
I don't know what you're talking about, and am not going to guess.
You seem to be suggesting that people regularly use partial
specialization to do something along these lines:

template < int N, typename T >
class MyClass {
T vals[ N ];
T func () const;
};

template < typename T >
class MyClass< 4, T > {
T vals[ 4 ];
T different_func () const;
};

That looks like a pretty bad design to me - a user would have no
reason to expect that the set of member functions in MyClass< 4, float
would be totally different from the set in MyClass< 3, double >,
without exhaustively searching through all the headers to make sure
they've found all the possible specializations.


-stephen diverdi
(e-mail address removed)
 
V

Victor Bazarov

Please explain to me then what is the advantage of creating a partial
specialization versus creating an entirely separate template class
then?

WTF do you mean? A separate class template cannot have the same name,
so if your class template is used somewhere and referred by its name,
having a separate class template is non-sensical. So, the advantage is
that you can accomplish something with a template specialisation which
you can't accomplish with ANYTHING ELSE.
I was replying to your statement in a previous post that "you can
accomplish the same thing with inheritance", which you seem to be
making again in this post. This is categorically false.

Again, I have no idea what you mean and thus I don't see any relevance.
Templates provide a way to parameterize aspects your class definition,
while inheritance provides a way for objects to assume the properties
of many different related types at run time. The way templates and
inheritance differ is separate from the way partial specialization is
handled, as compared to subclassing. Even if partial specialization
of templates propogated APIs the same way inheritance does, they would
still be fundamentally different constructs and would still serve
fundamentally different purposes.

I am now not sure you understood my initial suggestion, or perhaps its
meaning has mutated in your mind since we started this debate, but it
seems that you just don't [want to] see what I was suggesting and why
I was suggesting it. Too bad.
Please propose a way create a set of vector classes using
inheritance. I would like one class for each combination of
{int,float,double} and {2,3,4}-dimensions. They should all have the
same API, though the implementations for the different dimensions will
differ (for performance reasons). I would also like compile-time
typechecking and conversion for operations among these types.

Do your own development, will you? I am not going to solve all the
problems you have, but in the example that started this discussion
you _can_ put the *common* functionality in a base class and put the
*different* functionality in each of the specialisations *without*
requiring that specialisation mechanism provides *inheritance* of
the behaviour you don't want to change.
You seem to be suggesting that people regularly use partial

I am not suggesting what "people regularly use" any C++ mechanisms
for. I can only attest to what *I* use them for. I can *suggest*
what others *might what to consider* using some C++ mechanisms for.
What everybody does in their development it's up to them.
specialization to do something along these lines:

template < int N, typename T >
class MyClass {
T vals[ N ];
T func () const;
};

template < typename T >
class MyClass< 4, T > {
T vals[ 4 ];
T different_func () const;
};

That looks like a pretty bad design to me - a user would have no
reason to expect that the set of member functions in MyClass< 4, float
would be totally different from the set in MyClass< 3, double >,
without exhaustively searching through all the headers to make sure
they've found all the possible specializations.

You're twisting my arguments and pulling your examples "by the ears"
to suit your point of view. I never suggested that a specialisation
*should* have a different interface. It is entirely up to you, the
interface designer.

What I do suggest is, if you have to have a common _interface_ in
all specialisations of your template, plus you need some different
behaviour, instead of *requesting* the language to change to suit
your needs you use the mechanism provided. Here is the example:

template<class T> class Foo {
void dosomething() {}
static std::size_t get_id() { return glb_reg(Foo); }
};

template<class T> class Foo<T*> { // partial specialisation
void dosomething() {}
static std::size_t get_id() { return ptr_reg(Foo); }
};

According to you, the partial specialisation should allow one to
omit defining 'dosomething' in the second 'Foo' template:

template<class T> class Foo {
void dosomething() {}
static std::size_t get_id() { return glb_reg(Foo); }
};

template<class T> class Foo<T*> { // partial specialisation
// void dosomething() {} "inherited"
static std::size_t get_id() { return ptr_reg(Foo); }
};

What I am saying is that it shouldn't since a solution is available
using the inheritance mechanism:

template<class T> class Foo_Base {
void dosomething() {}
};

template<class T> class Foo : Foo_Base<T> {
// void dosomething() {} inherited here
static std::size_t get_id() { return glb_reg(Foo); }
};

template<class T> class Foo<T*> : Foo_Base<T*> { // partial
specialisation
// void dosomething() {} inherited here as well
static std::size_t get_id() { return ptr_reg(Foo); }
};

Do you get it now?


V
 
S

stephen.diverdi

Victor, I appreciate you taking the time to discuss this with me, but
I'd appreciate it a lot more without the attitude. I'm not interested
in getting into "i-said-you-said" bickering with you, nor do I care
what you think of what's going on in my brain, though thanks for
venturing the guesses.

The example you provided is indeed helpful, and now I (finally)
understand what you're suggesting. It is also now (finally) clear
that this in no way helps with my original question of how to get
around having to copy the entire definition of std::allocator for my
partial specialization. Guess I'm stuck with that.

Enjoy your pleasant banter with the other developers on here, and I'm
sure I'll see you again before too long. Thanks again,

-stephen diverdi
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,771
Messages
2,569,587
Members
45,099
Latest member
AmbrosePri
Top