Topic: Asymmetry in template specialization
Author: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/06/25 Raw View
On 24 Jun 1999 21:49:33 GMT, Andrei Alexandrescu <andrewalex@hotmail.com> wrote:
>Given the view above, it comes naturally to partially specialize some
>member functions for the first degree of freedom, some for the second,
>and some for both. The most general member functions don't need to be
>specialized at all. (Those are the very basics of the concept, its
>invariants, without which A wouldn't be an A anymore.)
>
>This method of design seems very powerful to me as you can achieve m *
>n behaviors by writing m + n functions. The compiler will take care of
>combining them appropriately. This scales to multiple values for each
>parameter (in my code they are enumerated types, not bool) and to
>multiple template parameters.
How is the compiler to combine them appropriately? Eg,
enum X { x1, x2, x3, x4 };
enum Y { y1, y2, y3 };
template <X,Y> class Concept { public: void f() const; };
There are 4*3==12 possible Concept classes, and according to what
you say, we must write 4+3==7 functions. I don't understand how
you intend to do this.
The only way I can think of is this:
// Concept.hh
enum X { x1, x2, x3, x4 };
enum Y { y1, y2, y3 };
template <X,Y> class Concept { public: void f() const; };
// Concept.cc
#include "Concept.hh"
namespace {
template <X> void fx() { }
template <> void fx<x1>() { ... }
template <> void fx<x2>() { ... }
template <> void fx<x3>() { ... }
template <> void fx<x4>() { ... }
template <Y> void fy() { }
template <> void fy<y1>() { ... }
template <> void fy<y2>() { ... }
template <> void fy<y3>() { ... }
}
template <X x, Y y> export
Concept<X,Y>::f() { fx<x>(); fy<y>(); }
We have specified how to compiler is to combine the X and Y parts of
Concept -- namely do the X part first, then the Y part.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Andrei Alexandrescu <andrewalex@hotmail.com>
Date: 1999/06/24 Raw View
In article <oryahb2ypd.fsf@saci.lsd.dcc.unicamp.br>,
Alexandre Oliva <oliva@dcc.unicamp.br> wrote:
> > template <class T> class A { void f() { } };
> > template <> void A<int>::f() { };
>
> Yup. But note that, in this case, you're referring to an existing
> template specialization, because referring to A<int> would cause its
> implicit instantiation. This is not the case for partial
> specializations; that's why you must declare and define them before
> defining a member function for the specialization.
Thanks for your patience. However, I was asking not whether this is
happening, but *why*. Why the hack?!?!?!?
> Because A<int> would be implicitly instantiated at the point of that
> declaration (if it hadn't been implicitly instantiated before that),
> the compiler would be able to tell whether the member function exists
> not.
I *want* this. I really *want* it. I want a partial specialization to
be instantiated implicitly if I define a member function of it (if I
haven't already done that). I don't see any technical reason for not
doing it this way, and it's much more consistent with the total
specialization situation.
> You'll probably have to use overloaded friend template functions :-(
I found a hack:
template <bool a, bool b>
class A
{
void f() { f<a>(); }
template <bool c> void f();
template <> void f<false>()
{
// treat the case when a==false
}
template <> void f<true>()
{
// treat the case when a==true
}
};
To the best of my knowledge and my understanding of the Standard, this
is 100% legal. However, it's a darned hack nonetheless which obscures
my intent.
Let me tell you why I think the technique is important. In the example
above, a and b are degrees of freedom of the concept A. For instance -
a means 'be single-threaded or multithreaded', and b means 'perform
lazy initialization or eager initialization'.
(The degrees of freedom are orthogonal on each other when they don't
interact in any way. As always, finding orthogonal decomposition leads
to the simplest code.)
The structure of the class may remain the same, however some of its
member functions may differ depending upon one of the parameters, or
both (the latter if the degrees of freedom aren't orthogonal).
Given the view above, it comes naturally to partially specialize some
member functions for the first degree of freedom, some for the second,
and some for both. The most general member functions don't need to be
specialized at all. (Those are the very basics of the concept, its
invariants, without which A wouldn't be an A anymore.)
This method of design seems very powerful to me as you can achieve m *
n behaviors by writing m + n functions. The compiler will take care of
combining them appropriately. This scales to multiple values for each
parameter (in my code they are enumerated types, not bool) and to
multiple template parameters.
I wrote incredibly tight template code that covers a lot of design
situations and decisions employing very few lines. (The hack that I had
to resort to made things a bit worse.)
For this reason I am very serious about proposing a change to the
language. Too sad I started with too a jokingly post to be taken
seriously, and that most C++ experts are so busy with the C++ versus
EC++ wars.
Andrei
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Andrei Alexandrescu <andrewalex@hotmail.com>
Date: 1999/06/22 Raw View
template <class T> class A { };
In article <orbteb75od.fsf@saci.lsd.dcc.unicamp.br>,
Alexandre Oliva <oliva@dcc.unicamp.br> wrote:
> Moreover, the intent here was to define a member function for a
> particular specialization of a template class. This can only be done
> after that particular specialization of the class has been defined.
> Remember that the body of a template class specializations may be
> completely different from the body of the unspecialized template
> class. It wouldn't make much sense to allow a specialized definition
> of a member function if the template class was to be specialized in a
> way that the member function didn't even exist.
Your argument would have made a point if total specializations of
member functions were NOT allowed. The following code is 100% legal, to
the best of my knowledge:
template <class T> class A { void f() { } };
template <> void A<int>::f() { };
A<char> a1; // a1.f() would use the general version
A<int> a2; // a2.f() would use the specialized version
Yet you could have said: "This is impossible. The specialization for
A<int> could look totally different an might even not have a member
function f()".
The total specialization of member functions and partial specialization
of member functions have precisely the same issues.
I repeat my question: why total specialization of member functions does
NOT require full class specialized and partial sepcialization does?
I have a class that's structurally the same, only some algorithms
differ. For serious reasons, I want to select the algorithms at compile
time.
Andrei
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Alexandre Oliva <oliva@dcc.unicamp.br>
Date: 1999/06/23 Raw View
On Jun 22, 1999, Andrei Alexandrescu <andrewalex@hotmail.com> wrote:
> In article <orbteb75od.fsf@saci.lsd.dcc.unicamp.br>,
> Alexandre Oliva <oliva@dcc.unicamp.br> wrote:
>> Moreover, the intent here was to define a member function for a
>> particular specialization of a template class. This can only be done
>> after that particular specialization of the class has been defined.
> Your argument would have made a point if total specializations of
> member functions were NOT allowed. The following code is 100% legal, to
> the best of my knowledge:
> template <class T> class A { void f() { } };
> template <> void A<int>::f() { };
Yup. But note that, in this case, you're referring to an existing
template specialization, because referring to A<int> would cause its
implicit instantiation. This is not the case for partial
specializations; that's why you must declare and define them before
defining a member function for the specialization.
> Yet you could have said: "This is impossible. The specialization for
> A<int> could look totally different an might even not have a member
> function f()".
Because A<int> would be implicitly instantiated at the point of that
declaration (if it hadn't been implicitly instantiated before that),
the compiler would be able to tell whether the member function exists
not.
> I repeat my question: why total specialization of member functions does
> NOT require full class specialized and partial sepcialization does?
Both do; it's just that, in the case of full specialization of member
function, an implicit specialization of the class template takes
place.
> I have a class that's structurally the same, only some algorithms
> differ. For serious reasons, I want to select the algorithms at compile
> time.
You'll probably have to use overloaded friend template functions :-(
--
Alexandre Oliva http://www.dcc.unicamp.br/~oliva IC-Unicamp, Bra[sz]il
{oliva,Alexandre.Oliva}@dcc.unicamp.br aoliva@{acm.org,computer.org}
oliva@{gnu.org,kaffe.org,{egcs,sourceware}.cygnus.com,samba.org}
*** E-mail about software projects will be forwarded to mailing lists
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Andrei Alexandrescu <andrewalex@hotmail.com>
Date: 1999/06/20 Raw View
It was a nice summer day. I was happily coding at home (click-click-
clack), when suddenly the compilers I have refused to compile my code.
They are two of the most standard-compliant compilers today. (Which of
course means a certain compiler for a certain platform built by a
certain company is not among them.) The code boiled down to this:
template <bool a, bool b>
struct A
{
void f() {}
};
// partially specialize f() for A<any, true>
template <bool a> void A<a, true>::f()
{
}
"Oh, another incompatibility with the Standard. Sigh", I mumbled and
opened Acrobat Reader.
Trying hard to keep my eyes from popping off my head, I couldn't find
in the section on partial specialization (14.5.4) any mentioning of
template partial specialization for functions. It's true I didn't find
an explicit dismissal of them, either.
Whatta hack is goin' on?
Total specialization for member function is allowed, though:
// totally specialize f() for A<false, true>
template <> void A<false, true>::f()
{
std::cout << "Works like a charm" << std::endl;
}
Plus, what I want to do is doable, but only via a darned hack:
template <bool a, bool b>
struct A
{
template <bool c> g() { }
template <> g<true>() { }
void f()
{
g<b>();
}
};
The problem is, it makes my intent almost impenetrable to the reader of
my code. In the first version, my intent was clearly put: I wanted to
write a specialized f() for b==true, no matter how a was. The hack is
bad, and it doesn't scale quite nicely (I actually have three
parameters in my class).
In my opinion, this feature lack introduces unnecessary asymmetry, and
disables what I think it is an important design technique. Imagine
yourself explaining the first version of the code, and explaining the
second.
The question is obvious. Why is total specialization of member
functions allowed, but partial specialization is not?
Andrei
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/06/20 Raw View
On 20 Jun 99 03:34:26 GMT, Andrei Alexandrescu <andrewalex@hotmail.com> wrote:
>struct A
>{
> void f() {}
>};
>
>// partially specialize f() for A<any, true>
>template <bool a> void A<a, true>::f()
>{
>}
This is not correct. Specializations outside the class definition are
not allowed. Some say that specializations inside the class definition
are also not allowed, although I think that they are allowed.
>template <bool a, bool b>
>struct A
>{
> template <bool c> g() { }
> template <> g<true>() { }
> void f()
> {
> g<b>();
> }
>};
Compiler como (an EDG compiler) forbids the specialization inside the
class definition. The error message: "explicit specialization is not
allowed in the current scope".
Compiler egcs allows the specialization, or so it seems. So it gives
no compile errors, but instead it gives a weird assembler error:
"Fatal error: Symbol g__H1b1_t1A2bY01bY11_v already defined".
>The question is obvious. Why is total specialization of member
>functions allowed, but partial specialization is not?
Total and partial specialization outside the class definition is not
allowed, and two excellents compilers indeed don't allow it.
Total and partial specialization inside the class definition I'm not
clear on. One of my compilers forbids it, and the other seems to
accept it.
Which two compilers are you using?
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Alexandre Oliva <oliva@dcc.unicamp.br>
Date: 1999/06/20 Raw View
On Jun 20, 1999, sbnaran@localhost.localdomain (Siemel Naran) wrote:
> This is not correct. Specializations outside the class definition are
> not allowed.
Why not? Specializations are *only* allowed in namespace scope.
> Some say that specializations inside the class definition
> are also not allowed, although I think that they are allowed.
The C++ Grammar doesn't accept specializations in class scope.
Moreover, the intent here was to define a member function for a
particular specialization of a template class. This can only be done
after that particular specialization of the class has been defined.
Remember that the body of a template class specializations may be
completely different from the body of the unspecialized template
class. It wouldn't make much sense to allow a specialized definition
of a member function if the template class was to be specialized in a
way that the member function didn't even exist.
> Compiler egcs allows the specialization, or so it seems.
The latest development snapshot rejects it, as it should.
>> The question is obvious. Why is total specialization of member
>> functions allowed, but partial specialization is not?
> Total and partial specialization outside the class definition is not
> allowed, and two excellents compilers indeed don't allow it.
See above. The problem is that a member can only be defined for an
already-declared (partial specialization of a) template class.
--
Alexandre Oliva http://www.dcc.unicamp.br/~oliva IC-Unicamp, Bra[sz]il
{oliva,Alexandre.Oliva}@dcc.unicamp.br aoliva@{acm.org,computer.org}
oliva@{gnu.org,kaffe.org,{egcs,sourceware}.cygnus.com,samba.org}
*** E-mail about software projects will be forwarded to mailing lists
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]