Topic: Declaring templates in class scope


Author: doug@monet.ads.com (Doug Morgan)
Date: 15 Dec 94 11:59:23
Raw View
In article <D0t5Kv.65F@ucc.su.OZ.AU> maxtal@physics.su.OZ.AU (John Max Skaller) writes:
|...
|    Thus you are agreeing with me that a class with
|template members is not a class. Because encapsulation
|is fundamental to OO and the C++ notion of classes.
|I do not mean all classes are encapsulated well, I mean
|it is _possible_ to encapsulate them. I'm not sure that
|without restriction it is _possible_ to protect the
|representation of a class with a template member.

Of course I agree that a class-with-template-members is not a class.
That's a good observation.  Now, accepting that observation, my point
was why expect a theory of encapsulation for something that is most
definitely not a class?  Thinking through the consequences of writing
different class-with-template-members things is very helpful and your
example are great.

Doug
----------
Doug Morgan, doug@ads.com, (415) 960-7444
Advanced Decision Systems (a division of Booz-Allen & Hamilton Inc.)
1500 Plymouth St., Mountain View, CA 94043-1230
----------




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Wed, 14 Dec 1994 15:55:42 GMT
Raw View
In article <DOUG.94Dec12111950@monet.ads.com> doug@monet.ads.com (Doug Morgan) writes:
>|    All is not as obvious as it seems. For example,
>|without some restrictions or rules one might assume it
>|is _possible_ to specialise a template member. Agree?
>
>I would think so.
>
>|    And if you can, you can violate encapsulation. Agree?
>
>I'm don't think so.  Anything with a template associated with it is
>essentially a macro.  The ability of a macro to expand depends on the
>context and specifics of expansion.  If someone want to think of a
>base class-thingie with template members, as some kind of class, then
>they might complain about violation of encapsulation.  However, with
>template-things considered just as specifications for macro expansion,
>I suspect that the concept of violating encapsulation isn't too
>relevent.

 Thus you are agreeing with me that a class with
template members is not a class. Because encapsulation
is fundamental to OO and the C++ notion of classes.
I do not mean all classes are encapsulated well, I mean
it is _possible_ to encapsulate them. I'm not sure that
without restriction it is _possible_ to protect the
representation of a class with a template member.
--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189




Author: matt@physics10.berkeley.edu (Matt Austern)
Date: 14 Dec 1994 19:04:46 GMT
Raw View
In article <D0t5Kv.65F@ucc.su.OZ.AU> maxtal@physics.su.OZ.AU (John Max Skaller) writes:

>  Thus you are agreeing with me that a class with
> template members is not a class. Because encapsulation
> is fundamental to OO and the C++ notion of classes.
> I do not mean all classes are encapsulated well, I mean
> it is _possible_ to encapsulate them. I'm not sure that
> without restriction it is _possible_ to protect the
> representation of a class with a template member.

That's a good point, and one that didn't occur to me when I asked my
question about declaring template member functions.

The most dangerous facility, of course, is the ability to specialize a
template function.  Do the rules approved by the standardization
committee say anything about specialization of template member
functions (e.g., do they explicitly say either that it is always
permitted or that it is permitted only in class scope), or is
specializatiton of template member functions simply covered by the
general rules about template function specialization?
--

                               --matt




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Wed, 14 Dec 1994 16:28:38 GMT
Raw View
In article <D0qq5r.IyI@cwi.nl> olaf@cwi.nl (Olaf Weber) writes:
>In article <D0pAoG.I30@ucc.su.OZ.AU>, maxtal@physics.su.OZ.AU (John Max Skaller) writes:
>
>>  All is not as obvious as it seems. For example,
>> without some restrictions or rules one might assume it
>> is _possible_ to specialise a template member. Agree?
>
>>  And if you can, you can violate encapsulation. Agree?
>
>On both counts.
>
>A possible solution could be a rule that specializations of template
>members must be declared in their class' scope.

 Yes. That would prevent encapsulation being violated.
A weaker for of the rule would permit protected and
read only private access -- you can only mutate _private_
variables with a declared specialisation, but you can read them.
That might be a reasonable compromise.
>
>It could be generalized to apply to namespaces, so that
>
> namespace N {
>  template <class T> void f(T);
> };
>
> void N::f<char*>(char*) { /* ... */ }
>
>becomes illegal as well.

 Thats no good. Namespaces are not encapsulated.
An option I have considered is to allow specialisations
in namespaces _other_ than that of the original template;
these would be localised to that namespace and so not
clash with each other or the "master" version.

 However there are problems with this approach.

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Thu, 15 Dec 1994 15:51:34 GMT
Raw View
In article <MATT.94Dec14110446@physics10.berkeley.edu> matt@physics.berkeley.edu writes:
>In article <D0t5Kv.65F@ucc.su.OZ.AU> maxtal@physics.su.OZ.AU (John Max Skaller) writes:
>
>>  Thus you are agreeing with me that a class with
>> template members is not a class. Because encapsulation
>> is fundamental to OO and the C++ notion of classes.
>> I do not mean all classes are encapsulated well, I mean
>> it is _possible_ to encapsulate them. I'm not sure that
>> without restriction it is _possible_ to protect the
>> representation of a class with a template member.
>
>That's a good point, and one that didn't occur to me when I asked my
>question about declaring template member functions.
>
>The most dangerous facility, of course, is the ability to specialize a
>template function.  Do the rules approved by the standardization
>committee say anything about specialization of template member
>functions (e.g., do they explicitly say either that it is always
>permitted or that it is permitted only in class scope), or is
>specializatiton of template member functions simply covered by the
>general rules about template function specialization?

 I'm not aware of any restrictions -- assuming it is
possible to specialise a template member at all.

 I'm not sure that such restrictions would be a good idea
either. It could be template members are most effective
_because_ they permit controlled violation of encapsulation.

 For example:

 class Number {
  template<class T> void AddOn(T);
 };

This is a template version of the proverbial multi-method.
A Number can be added to anything (T) -- but its _necessary_
to defer the implementation until T is known, and it may
well be logically necessary for that implementation to
access the private details of Number.

Why? Because if it were not necessary, you could use
a global non-friend function instead.

There is no surprise here -- you cant have both
multi-polymorphism and encapsulation.

Note that the _nice_ thing about member templates is that
while access is NOT locked into a fixed set of known
functions, at least an explicit "hook" is required to
gain access. I.e. if we're going to write representation
dependent code, we can at least track it down on
a per program basis.

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189




Author: doug@monet.ads.com (Doug Morgan)
Date: 12 Dec 94 11:19:50
Raw View
In article <D0pAoG.I30@ucc.su.OZ.AU> maxtal@physics.su.OZ.AU (John Max Skaller) writes:
|In article <DOUG.94Dec11014602@monet.ads.com> doug@monet.ads.com (Doug Morgan) writes:
|>|>> >    class foo {
|>|>> >        // ...
|>|>> >        template<class Functor> double Eval(Functor f);
|>|>> >    };
|>|>
|>|>>  foo is not a class. classes don't have infinite members.
|>|>>  Its something else, for which  there is no coherent theory
|>|>>  (yet).
|>|... [interesting examples]...
|>|The point really? We just do not know what the consequences are.
|>
|>Your examples seem unambiguous as to when programs are OK, shouldn't
|>compile, and have undefined behavior.  The theory seem quite coherent.
|>As for unknown consequences, Meyers is going to have to write 50++
|>someday, anyway.  What difference does another topic or two make?
|
|    All is not as obvious as it seems. For example,
|without some restrictions or rules one might assume it
|is _possible_ to specialise a template member. Agree?

I would think so.

|    And if you can, you can violate encapsulation. Agree?

I'm don't think so.  Anything with a template associated with it is
essentially a macro.  The ability of a macro to expand depends on the
context and specifics of expansion.  If someone want to think of a
base class-thingie with template members, as some kind of class, then
they might complain about violation of encapsulation.  However, with
template-things considered just as specifications for macro expansion,
I suspect that the concept of violating encapsulation isn't too
relevent.

I would actually much prefer it if C++ had a more powerful
template/macro language that gave me the opportunity to *really*
violate encapsulation.  However, that probably would be a big minus
for the general usefulness of C++, so I'm pretty much contented with
seeing template members showing up.  Although, it's too bad about
template virtual functions not making it --- dumb linkers and the
reliance on dispatch tables as *the* blessed implementation of virtual
dispatch strike again.

Doug
----------
Doug Morgan, doug@ads.com, (415) 960-7444
Advanced Decision Systems (a division of Booz-Allen & Hamilton Inc.)
1500 Plymouth St., Mountain View, CA 94043-1230
----------





Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: Tue, 13 Dec 1994 06:50:22 GMT
Raw View
ark@research.att.com (Andrew Koenig) writes:

>maxtal@physics.su.OZ.AU (John Max Skaller) writes:
>
>> >    class foo {
>> >        // ...
>> >        template<class Functor> double Eval(Functor f);
>> >    };
>
>>  foo is not a class. classes don't have infinite members.
>>  Its something else, for which  there is no coherent theory
>>  (yet).
>
>For any particular program that uses foo, the member template can be
>replaced with a finite number of non-template declarations with equivalent
>effect.  The implication that foo has inifinite members is therefore
>misleading.

Yes, you are correct - John Max should have used the word "unbounded".

Nevertheless, there is at least one significant implication of classes
whose members are not bounded at class definition time: encapsulation
is weakened.  This is because anyone can come along and provide new
specializations of member templates which use the class's private
members.  If a library vendor provides a class with a template member,
and they want to make sure that they can change the class
implementation without breaking user code, then they had better
*document* that if users specialize the template member, they should not
use the class' private members - the compiler will not *enforce* this.

(Notwithstanding the above, I think allowing member templates is probably
a good thing.)

As regards theory - is there any coherent theory of C++ classes at all? :-)

--
Fergus Henderson - fjh@munta.cs.mu.oz.au




Author: olaf@cwi.nl (Olaf Weber)
Date: Tue, 13 Dec 1994 08:27:30 GMT
Raw View
In article <D0pAoG.I30@ucc.su.OZ.AU>, maxtal@physics.su.OZ.AU (John Max Skaller) writes:

>  All is not as obvious as it seems. For example,
> without some restrictions or rules one might assume it
> is _possible_ to specialise a template member. Agree?

>  And if you can, you can violate encapsulation. Agree?

On both counts.

A possible solution could be a rule that specializations of template
members must be declared in their class' scope.

That would allow

 class C {
 public:
  template <class T> void f(T);
  void f<char*>(char*);
 };

 void C::f<char*>(char*) { /* ... */ }

while disallowing

 class B {
 public:
  template <class T> void f(T);
 };

 void B::f<char*>(char*) { /* ... */ }

It could be generalized to apply to namespaces, so that

 namespace N {
  template <class T> void f(T);
 };

 void N::f<char*>(char*) { /* ... */ }

becomes illegal as well.

Comments regarding the (un)desirability of the member-template or the
generalized rule are welcome.

-- Olaf Weber




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sun, 11 Dec 1994 03:52:03 GMT
Raw View
In article <D0IJ4L.F14@research.att.com> ark@research.att.com (Andrew Koenig) writes:
>In article <D0HyLI.K8K@ucc.su.OZ.AU> maxtal@physics.su.OZ.AU (John Max Skaller) writes:
>
>> >    class foo {
>> >        // ...
>> >        template<class Functor> double Eval(Functor f);
>> >    };
>
>>  foo is not a class. classes don't have infinite members.
>>  Its something else, for which  there is no coherent theory
>>  (yet).
>
>For any particular program that uses foo, the member template can be
>replaced with a finite number of non-template declarations with equivalent
>effect.  The implication that foo has inifinite members is therefore
>misleading.

 The point is that the members of a class
in a library are fixed in the library. The fact that the members
in any particular program are finite is no more relevant than
saying that the number of instances of a template in any
program are finite.

 That is, I used the word "infinite" synonymously
with "arbitrary", which is perhaps misleading. My point is
that just as a class template is not a class, so too
a class containing a template member is not a class.

 The point is that the programmer using a class
can call on a service (member) which takes an argument
type just invented by that programmer and which the
library could not have known about. That is,
the class with the member template is extensible, just
like a template.

 There are some interesting consequences. For example:

 class X {
  template<class T> operator T()const;
 };

 void f(int);
 void f(long);
 X x;
 f(x); // guarranteed to be ambiguous

That means that if you have a working program like

 X x;
 g(x);

then you must not overload g later. And _that_ means that notionally
there is a kind of function which is intended to be overloaded
and another which is intended not to be overloaded.

Or perhaps the rule is you must provide a

 g(X); // disambiguate

and then every time you add a new class with a template operator
conversion you have to extend the overload set of g to include X.

Exactly which "subtitutions" for T are permitted here is
crucial. If you just follow the type system you are in
serious trouble.

For example:

 g(const A&);
 g(x); // guarranteed to fail usually

The reason is that a conversion written in the member template
is probably intended as an OBJECT conversion. Either
the substitution

 T-->X const&

is disallowed as a viable deduction, or it is permitted
and the code of the member template fails to compile -- or
even worse crashes. For example:

 class X {
  int i;
  template <class T> operator T()const { return i; }
 };
 X x;
 g(long const&);
 g(x);

acts as if the class X had a member

 operator long const&()const { return i; }

which returns a reference to a temporary which evaporates
before g is actually called.

So the ability of the class library designer to _constrain_
or _encapsulate_ the semantics is lost.

The point really? We just do not know what the consequences are.
Guess we'll find out :-)

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189




Author: doug@monet.ads.com (Doug Morgan)
Date: 11 Dec 94 01:46:02
Raw View
In article <D0Mo2r.EHn@ucc.su.OZ.AU> maxtal@physics.su.OZ.AU (John Max Skaller) writes:
|In article <D0IJ4L.F14@research.att.com> ark@research.att.com (Andrew Koenig) writes:
|>In article <D0HyLI.K8K@ucc.su.OZ.AU> maxtal@physics.su.OZ.AU (John Max Skaller) writes:
|>
|>> >    class foo {
|>> >        // ...
|>> >        template<class Functor> double Eval(Functor f);
|>> >    };
|>
|>>  foo is not a class. classes don't have infinite members.
|>>  Its something else, for which  there is no coherent theory
|>>  (yet).
|... [interesting examples]...
|The point really? We just do not know what the consequences are.

Your examples seem unambiguous as to when programs are OK, shouldn't
compile, and have undefined behavior.  The theory seem quite coherent.
As for unknown consequences, Meyers is going to have to write 50++
someday, anyway.  What difference does another topic or two make?

Doug
----------
Doug Morgan, doug@ads.com, (415) 960-7444
Advanced Decision Systems (a division of Booz-Allen & Hamilton Inc.)
1500 Plymouth St., Mountain View, CA 94043-1230
----------




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Mon, 12 Dec 1994 13:55:26 GMT
Raw View
In article <DOUG.94Dec11014602@monet.ads.com> doug@monet.ads.com (Doug Morgan) writes:
>|>> >    class foo {
>|>> >        // ...
>|>> >        template<class Functor> double Eval(Functor f);
>|>> >    };
>|>
>|>>  foo is not a class. classes don't have infinite members.
>|>>  Its something else, for which  there is no coherent theory
>|>>  (yet).
>|... [interesting examples]...
>|The point really? We just do not know what the consequences are.
>
>Your examples seem unambiguous as to when programs are OK, shouldn't
>compile, and have undefined behavior.  The theory seem quite coherent.
>As for unknown consequences, Meyers is going to have to write 50++
>someday, anyway.  What difference does another topic or two make?

 All is not as obvious as it seems. For example,
without some restrictions or rules one might assume it
is _possible_ to specialise a template member. Agree?

 And if you can, you can violate encapsulation. Agree?

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189




Author: matt@physics10.berkeley.edu (Matt Austern)
Date: 07 Dec 1994 23:17:35 GMT
Raw View
Many existing compilers restrict template definitions to global scope,
as opposed to class scope---that is, they do not allow member
functions to be template functions.  (Except, of course, in the sense
that every member function of a template class is implicitly a
template function.)

This means that a declaration like

    class foo {
        // ...
        template<class Functor> double Eval(Functor f);
    };

is prohibited.  (Which is a pity, since I'd like to write something
very much like this in the program I'm working on right now.)

Two questions: (1) Is this consistent with the latest wording in the
C++ "standard"?  (2) If so, what is the rationale for this
restriction?

--

                               --matt




Author: jason@cygnus.com (Jason Merrill)
Date: Thu, 8 Dec 1994 01:25:07 GMT
Raw View
>>>>> Matt Austern <matt@physics10.berkeley.edu> writes:

> Many existing compilers restrict template definitions to global scope,
> as opposed to class scope---that is, they do not allow member
> functions to be template functions.  (Except, of course, in the sense
> that every member function of a template class is implicitly a
> template function.)

> (1) Is this consistent with the latest wording in the C++ "standard"?

No; templates can now be class members.

Jason




Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 8 Dec 1994 01:44:02 GMT
Raw View
matt@physics10.berkeley.edu (Matt Austern) writes:

>Many existing compilers restrict template definitions to global scope,

Yes, because that is what the ARM says.

>This means that a declaration like

>    class foo {
>        // ...
>        template<class Functor> double Eval(Functor f);
>    };

>is prohibited.  (Which is a pity, since I'd like to write something
>very much like this in the program I'm working on right now.)

>Two questions: (1) Is this consistent with the latest wording in the
>C++ "standard"?  (2) If so, what is the rationale for this
>restriction?

The subject is discussed at length in "Design and Evolution". The
rationale is that templates weren't undertood well enough to predict
what bad results would ensue from allowing member templates. It is
easy to remove restrictions in a language, but hard to add them.

It became obvious that you couldn't allow a virtual function to be
a template (no practical way to predict the size of the vtable or
assign slots in separate compilations -- not to mention dynamic
libraries).

The C++ Committee voted to allow member templates for non-virtual
functions.
--
Steve Clamage, stephen.clamage@eng.sun.com




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Thu, 8 Dec 1994 14:51:17 GMT
Raw View
In article <MATT.94Dec7151736@physics10.berkeley.edu> matt@physics.berkeley.edu writes:
>
>This means that a declaration like
>
>    class foo {
>        // ...
>        template<class Functor> double Eval(Functor f);
>    };
>
>is prohibited.  (Which is a pity, since I'd like to write something
>very much like this in the program I'm working on right now.)
>

 Thats called a member template and it is now permitted.
 And it is a _very_ radical change.

 foo is not a class. classes don't have infinite members.
 Its something else, for which  there is no coherent theory
 (yet).
--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189




Author: brewin@Eng.Sun.COM (Bob Brewin)
Date: 8 Dec 1994 20:20:09 GMT
Raw View
In article 94Dec7172507@phydeaux.cygnus.com, jason@cygnus.com (Jason Merrill) writes:
> >>>>> Matt Austern <matt@physics10.berkeley.edu> writes:
>
> > Many existing compilers restrict template definitions to global scope,
> > as opposed to class scope---that is, they do not allow member
> > functions to be template functions.  (Except, of course, in the sense
> > that every member function of a template class is implicitly a
> > template function.)
>
> > (1) Is this consistent with the latest wording in the C++ "standard"?
>
> No; templates can now be class members.
>
> Jason

Provided that they are not virtual.

- Bob








Author: ark@research.att.com (Andrew Koenig)
Date: Thu, 8 Dec 1994 22:14:44 GMT
Raw View
In article <D0HyLI.K8K@ucc.su.OZ.AU> maxtal@physics.su.OZ.AU (John Max Skaller) writes:

> >    class foo {
> >        // ...
> >        template<class Functor> double Eval(Functor f);
> >    };

>  foo is not a class. classes don't have infinite members.
>  Its something else, for which  there is no coherent theory
>  (yet).

For any particular program that uses foo, the member template can be
replaced with a finite number of non-template declarations with equivalent
effect.  The implication that foo has inifinite members is therefore
misleading.
--
    --Andrew Koenig
      ark@research.att.com