Topic: Where are member specializations allowed?
Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Tue, 2 Jan 2007 12:00:38 CST Raw View
Simon G Best wrote:
> Recently, I tried to do the following:-
>
> template<typename T> class thingy {
> public:
> template<typename U> T f (const U &) const;
> };
>
> // The general case:-
> template<typename T> template<typename U> T thingy<T>::f
> (const U &x) const {
> return T(x);
> }
>
> // The special case:-
> template<typename T> template<> T thingy<T>::f<T> (const T &x) const {
> return x;
> }
>
> and it didn't work. I gather it's Not Allowed:-
No, that's Not Allowed - but this is:
template<typename T>
class thingy
{
public:
T f(const T& t) const;
template<typename U>
T f(const U& u) const;
};
// The general case:
template<typename T>
template<typename U>
T thingy<T>::f( const U& u) const
{
return T(u);
}
// The "special" case:
template<typename T>
T thingy<T>::f( const T& t) const
{
return t;
}
One advantage of overloading - instead of specializing - f() is to
extend the "special case" to include calls to f() with argument types
other than T (and T only). The f() overload will also execute whenever
f() is called with an argument of a type derived from T (or a type that
implicitly converts to T). For example, the specialized f() could
handle this call: f(5L) or this one: f(5) but never both (despite the
lack of any meaningful difference between the two calls.) The f()
overload in contrast can handle both calls identically.
> I'd really rather do it the way I originally tried, though. I don't yet
> see how allowing such specialisations would lead to ambiguities, so if
> someone could post an example to enlighten me, I'd appreciate it :-)
The original example faces a more immediate obstacle: namely that C++
does not allow function templates to be partially specialized. In other
words, it is not possible to provide a definition of the function
template f() that handles just the case when f()'s type parameter and
the type parameter of the thingy specialization of which f() is a
member - are one and the same type.
Now, why C++ does not allow function templates to be partially
specialized, I do not know for sure. I half-believe that the reason is
simply to prevent the rules for resolving overloaded function calls in
C++ from collapsing under the weight of their own complexity. On the
other hand, the C++ Standard is not known for capitulating in the face
of complexity. On the contrary, the Standard at times evinces an almost
boundless tolerance of (or appetite for?) complexity. So I would say
that this question is still quite open.
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: simon.g.best@btinternet.com (Simon G Best)
Date: Sat, 30 Dec 2006 18:42:59 GMT Raw View
Hello!
Recently, I tried to do the following:-
[Start C++ snippet here.]
template<typename T> class thingy {
public:
template<typename U> T f (const U &) const;
};
// The general case:-
template<typename T> template<typename U> T thingy<T>::f
(const U &x) const {
return T(x);
}
// The special case:-
template<typename T> template<> T thingy<T>::f<T> (const T &x) const {
return x;
}
[End C++ snippet here.]
and it didn't work. I gather it's Not Allowed:-
Greg Herlihy wrote:
> Nicola Musatti wrote:
[...]
>> On a related note, why are explicit specializations of member templates
>> of non specialized class templates forbidden?
>
> Since a member class template is a distinct template for each of its
> enclosing class template instantiations, being able to declare a full
> member specialization without an enclosinig class template
> specialization, would specialize - not just one member class template -
> but would in fact specialize an unlimited number of member class
> templates that would "cut across" the specializations of its enclosing
> class template. The member template would in effect be creating
> specializations of its enclosing class template that its enclosing
> class template would not itself be specializing.
>
> In effect, allowing a member template specialization by itself would
> mean that a member template could be specialized on either of two,
> different axes. And having two different ways to specialize the same
> template simply invites ambiguity and conflict - and would add no new
> capability to C++ templates in return. So while there are good
> arguments for making C++ templates more capable, there is no argument
> to be made for making them merely more complex.
I'm not convinced; it sounds a bit confused. The enclosing template and
the member template are clearly distinct, aren't they?
Anyway, I found that I could get something like what I wanted by doing
the following:-
[Start C++ snippet here.]
template<typename T> class thingy {
public:
template<typename U> T f (const U &) const;
};
namespace {
// The general case:-
template<typename T, typename U> class thingy_f_implementation {
public:
static T f (const U &x) { return T(x); }
};
// The special case:-
template<typename T> class thingy_f_implementation<T, T> {
public:
static T f (const T &x) { return x; }
};
}
template<typename T> template<typename U> T thingy<T>::f (const U &x)
const {
return thingy_f_implementation<T, U>::f(x);
}
[End C++ snippet here.]
It works, but does involve having that class thingy_f_implementation<>,
even if it's in an anonymous namespace. (If it's in a header (specially
as 'export' is often unimplemented), it'll get included in everything
that #includes that header.) But it does leave the interface of class
thingy<> unchanged, which seems right when the specialisation is only
for implementational reasons.
I'd really rather do it the way I originally tried, though. I don't yet
see how allowing such specialisations would lead to ambiguities, so if
someone could post an example to enlighten me, I'd appreciate it :-)
Simon
--
What happens if I mention Leader Kibo in my .signature?
---
[ 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: Thu, 9 Nov 2006 11:44:37 CST Raw View
Nicola Musatti wrote:
> If my reading of the standard is correct, member template partial
> specializations may be defined within the enclosing class definition,
> while member template explicit specializations may not. I base my
> conclusions on clause 14.7.3-2 which says:
> ...
> I wasn't unable to find similar text for partial specializations and
> the example in clause 14.5.4.3-2:
>
> template<class T> struct A {
> template<class T2> struct B {}; // #1
> template<class T2> struct B<T2*> {}; // #2
> };
> template<> template<class T2> struct A<short>::B {}; // #3
>
> appears to support my understanding. Is this difference intentional and
> if it is, what is the rationale behind it?
The difference is far more likely to be incidental - rather than
intentional. In other words, there probably is no rationale that
requires partial and full member specializations to be declared in
disinct locations. There probably is a deliberate intention to have any
kind of declaration appear at the location where it makes the most
sense for a declaration of that kind to be placed. So it is the
consequence of that rationale that no doubt accounts for the difference
here.
After all, it simply makes more sense for the declaration of a partial
specialization of a member template to appear within its enclosing
class template (since the partial specialization is reproduced in each
instantiation of the class template). Likewise, it also makes sense for
a full member specialzation to be declared outside of any other
template - by itself - since a full specialization describes a unique
type that stands on its own.
> On a related note, why are explicit specializations of member templates
> of non specialized class templates forbidden?
Since a member class template is a distinct template for each of its
enclosing class template instantiations, being able to declare a full
member specialization without an enclosinig class template
specialization, would specialize - not just one member class template -
but would in fact specialize an unlimited number of member class
templates that would "cut across" the specializations of its enclosing
class template. The member template would in effect be creating
specializations of its enclosing class template that its enclosing
class template would not itself be specializing.
In effect, allowing a member template specialization by itself would
mean that a member template could be specialized on either of two,
different axes. And having two different ways to specialize the same
template simply invites ambiguity and conflict - and would add no new
capability to C++ templates in return. So while there are good
arguments for making C++ templates more capable, there is no argument
to be made for making them merely more complex.
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: "Nicola Musatti" <nicola.musatti@gmail.com>
Date: Fri, 10 Nov 2006 09:51:13 CST Raw View
Greg,
I appreciate your attempt at being helpful, but I posted my query to
see if a defect report is in order for what looks like a contradiction
in the standard. Thus I'm seeking the actual rationale behind this
choice if there is one, rather than speculations which, while
interesting and sensible, do not carry much more weight than my own
ones.
Moreover your answer may have the effect of giving people in the know
the impression that my curiosity has already been satisfied and no
further answer is necessary, while this is not the case.
Cheers,
Nicola Musatti
---
[ 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: "Nicola Musatti" <nicola.musatti@gmail.com>
Date: Wed, 8 Nov 2006 09:47:19 CST Raw View
Hallo,
If my reading of the standard is correct, member template partial
specializations may be defined within the enclosing class definition,
while member template explicit specializations may not. I base my
conclusions on clause 14.7.3-2 which says:
"An explicit specialization shall be declared in the namespace of which
the template is a member, or, for member templates, in the namespace of
which the enclosing class or enclosing class template is a member. An
explicit specialization of a member function, member class or static
data member of a class template shall be declared in the namespace of
which the class template is a member. Such a declaration may also be a
definition. If the declaration is not a definition, the specialization
may be defined later in the namespace in which the explicit
specialization was declared, or in a namespace that encloses the one in
which the explicit specialization was declared."
I wasn't unable to find similar text for partial specializations and
the example in clause 14.5.4.3-2:
template<class T> struct A {
template<class T2> struct B {}; // #1
template<class T2> struct B<T2*> {}; // #2
};
template<> template<class T2> struct A<short>::B {}; // #3
appears to support my understanding. Is this difference intentional and
if it is, what is the rationale behind it?
On a related note, why are explicit specializations of member templates
of non specialized class templates forbidden?
Cheers,
Nicola Musatti
---
[ 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 ]