Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

VC++5.0 STL vector class

0 views
Skip to first unread message

Thomas Wood

unread,
Mar 21, 1997, 3:00:00 AM3/21/97
to

Has anyone else experienced a problem compiling code declaring an object
of type vector<> specifying your own class or a structure as the type?
When I write this line of code:

vector<CLSID, allocator<CLSID> > cv;

It worked fine in VC++4.2 but under 5.0 I get the following compiler
error:

binary '<' : no operator defined which takes a left-hand operand of type
'const struct _GUID'

The same thing occurs when the type is a class that does not have an
operator<() function or an operator==() function declared. Why does a
vector need to compare members for < or ==?

Dan Muller

unread,
Mar 22, 1997, 3:00:00 AM3/22/97
to

In article <33332B...@adnc.com>, wo...@adnc.com says...

Because template instantiation is now closer to compliance with the draft
standard. There are member functions in the standard containers that
require operator< and/or operator== be defined for the contained objects,
and these member functions are now instantiated and syntax-checked even
if you don't use them. I *believe* (but am not certain) that this
behavior is in compliance with the draft standard.

--
Dan Muller da...@ziplink.net
http://www.ziplink.net/~danm

Kevin Cao

unread,
Mar 22, 1997, 3:00:00 AM3/22/97
to

> vector<CLSID, allocator<CLSID> > cv;
>
> It worked fine in VC++4.2 but under 5.0 I get the following compiler
> error:
>
> binary '<' : no operator defined which takes a left-hand operand of type
> 'const struct _GUID'
>

I had the same problem. However by adding following line
using namespace std;
at the begining of the cpp file solved the problem.
Maybe it was just my luck. That is how the problem was fixed
with my program.


Mogens Hansen

unread,
Mar 22, 1997, 3:00:00 AM3/22/97
to

It is NOT compliant to the ANSI C++ Commite Draft to require operators
referenced
by not used member functions to be implemented. Not used member functions
should not be compiled, and need not be compileable!

Mogens Hansen


Joseph M. O'Leary

unread,
Mar 23, 1997, 3:00:00 AM3/23/97
to

CLSID is typedefed in the Visual C++ 5.0 header file WTYPES.H as follows.

typedef struct _GUID
{
DWORD Data1;
WORD Data2;
WORD Data3;
BYTE Data4[ 8 ];
} GUID;

...

typedef GUID CLSID;

This means that a CLSID is a structure. Since it has a simple C style
array you cannot user operator < to compare one CLSID to another. The
following code snippet will give you the same error you are seeing with
your vector.

CLSID clsid1, clsid2;
BOOL bStat = clsid1 < clsid2;

The vector template has a comparison function < for comparing one vector to
another. In the VC 5++ implementation, this member function calls the STL
lexicographical_compare template function which uses operator< against the
elements in the 2 vectors. This means, that the vector class generated for
you is comparing on CLSID against another.

Thus you have to write operator<(). Unfortunately, GUID is already
defined. You might want to try deriving a class from it that adds all of
the comparison operators you need. You can store these in your vector, and
cast them to CLSIDs when you need to.

Joe O'


Thomas Wood <wo...@adnc.com> wrote in article <33332B...@adnc.com>...


> Has anyone else experienced a problem compiling code declaring an object
> of type vector<> specifying your own class or a structure as the type?
> When I write this line of code:
>

> vector<CLSID, allocator<CLSID> > cv;
>
> It worked fine in VC++4.2 but under 5.0 I get the following compiler
> error:
>
> binary '<' : no operator defined which takes a left-hand operand of type
> 'const struct _GUID'
>

Dan Muller

unread,
Mar 23, 1997, 3:00:00 AM3/23/97
to

In article <01bc372c$5d35b1e0$0f552399@caffeine>, jmol...@earthlink.net
says...

>
> The vector template has a comparison function < for comparing one vector to
> another. In the VC 5++ implementation, this member function calls the STL
> lexicographical_compare template function which uses operator< against the
> elements in the 2 vectors. This means, that the vector class generated for
> you is comparing on CLSID against another.
>
> Thus you have to write operator<(). Unfortunately, GUID is already
> defined. You might want to try deriving a class from it that adds all of
> the comparison operators you need. You can store these in your vector, and
> cast them to CLSIDs when you need to.

No, no, no, you don't have to do anything that complicated. Just define
an unbound operator< for CLSID structs:

inline bool operator< (const CLSID& lhs, const CLSID& rhs)
{
// whatever...
}

I use something like this at work. Quite simple.

Joseph M. O'Leary

unread,
Mar 23, 1997, 3:00:00 AM3/23/97
to

Dan Muller <da...@ziplink.net> wrote in article
<MPG.d9e8db67...@news.ziplink.net>...

> No, no, no, you don't have to do anything that complicated. Just define
> an unbound operator< for CLSID structs:
>
> inline bool operator< (const CLSID& lhs, const CLSID& rhs)
> {
> // whatever...
> }
>
> I use something like this at work. Quite simple.

Thanks this reply. Much simpler and better (and more obvious -- duh) than
what I suggested.

Joe O'


Doug Harrison

unread,
Mar 23, 1997, 3:00:00 AM3/23/97
to

It's definitely a bug in VC5 (see the Dec-96 DWP, sections 14.7.1.2,
14.7.1.7, and 14.6.5). The workaround is to add both operator< and
operator== for classes you intend to instantiate vector on, so that VC5 can
erroneously instantiate template functions that you presumably aren't
using, that require classes that are comparable, such as vector::operator==
and vector::operator<.. I think this is a rather dangerous and
unsatisfactory workaround; many, if not most, classes simply aren't
comparable, and implementing bogus comparison operators promotes
programming errors. The following program fragment abstracts the problem:

--- q.cpp begins ---

template<class T>
struct bogus
{
void fun(T x) { x.fun(); }
};

bogus<int> x;

--- ends ---

Here's the compiler output:

F:\temp>cl -c q.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 11.00.7022 for 80x86
Copyright (C) Microsoft Corp 1984-1997. All rights reserved.

q.cpp
q.cpp(4) : error C2228: left of '.fun' must have class/struct/union type

F:\temp>

VC5 is erroneously instantiating bogus<int>::fun, and 14.7.1.7 prohibits
this, while the example given in 14.6.5 implies that the potential error in
this function must not be diagnosed, because bogus<X>::fun could be valid
for some X, and thus it should be diagnosed only if bogus<int>::fun is
actually instantiated. (You get a similar wrong result if you instantiate
bogus on a class type, e.g. "struct A {}; bogus<A> x;".)

--
Doug Harrison
dHar...@worldnet.att.net

Dan Muller

unread,
Mar 23, 1997, 3:00:00 AM3/23/97
to

[This followup was posted to microsoft.public.vc.language and a copy was
sent to the cited author.]

In article <01bc3709$165b3240$5211eac2@mogens>, Moge...@dk-online.dk
says...

Mogen, I went back and looked at the draft in more detail. We are both
right, but you're a lot more right than I was. :-) The situation is
different for implicit and explicit instantiation, but I didn't
understand what constitutes implicit instantiation for a class template
until I took another long look at the draft. Here's what I think I
learned:

template <T> class A {};
A<int> ai; // implicit instantiation
template A<char>; // explicit instantiation

In the implicit case, which is obviously the most common, member
functions that are not used should not be instantiated:

14.7.1 Implicit instantiation

7 An implementation shall not implicitly instantiate a function, non-
virtual member function, class or member template that does not
require instantiation. It is unspecified whether or not an implemen-
tation implicitly instantiates a virtual member function that does not
require specialization.


In the explicit case, however, *all* members must be instantiated:

14.7.2 Explicit instantiation

7 The explicit instantiation of a class template specialization implies
the instantiation of all of its members not previously explicitly spe-
cialized in the translation unit containing the explicit instantia-
tion. A member class of a class template may be explicitly instanti-
ated.


This makes much more sense that what I thought last week. My apologies to
anyone who was misled by any of my posts.

Now I have something else to add to the list of broken template behavior
in VC++.

The above quotes are from the Dec 1996 Working Paper, which I referenced
at the following URL:

http://www.cygnus.com/misc/wp/dec96pub/

Roger Nelson

unread,
Mar 24, 1997, 3:00:00 AM3/24/97
to

In article <01bc372c$5d35b1e0$0f552399@caffeine>, "Joseph M. O'Leary" <jmol...@earthlink.net> wrote:
> CLSID clsid1, clsid2;
> BOOL bStat = clsid1 < clsid2;
>
>The vector template has a comparison function < for comparing one vector to
>another.
(...)

>Thus you have to write operator<(). Unfortunately, GUID is already
>defined. You might want to try deriving a class from it that adds all of
>the comparison operators you need. You can store these in your vector, and
>cast them to CLSIDs when you need to.
>
I think a 'friend' function would allow avoiding to have to create a new
class.


Dan Muller

unread,
Mar 25, 1997, 3:00:00 AM3/25/97
to

In article <3339441d...@nntp.ix.netcom.com>, sgar...@world.std.com
says...
> does anyone have a work around for this (rather gigantic) bug?
> i'm looking for something that will allow me to continue using vc++5
> and touch as little existing (correctly written) code as possible.
>
> so, far, for my purposes, i've got two solutions (but, i'm still not
> happy with either).
>
> class A {
> ...
> operator int () { return 0; } // add when needed for vc5
> ...
> };
>
> or, as has been suggested:
>
> inline bool operator < (const struct A&, const struct A&) { return false; }
> inline bool operator == (const struct A&, const struct A&) { return false; }
>
> anyone have a better idea?
>

Well, I've seen someone mention providing a conversion to int, but that
seems even worse to me... Basically, this needs to be fixed in the
compiler. I really hope that this, template member support, and default
arguments in members of class templates all get fixed soon in a patch.

Scott Garland

unread,
Mar 25, 1997, 3:00:00 AM3/25/97
to

"Doug Harrison" <dHar...@worldnet.att.net> wrote:
>
>VC5 is erroneously instantiating bogus<int>::fun, and 14.7.1.7 prohibits
>this, while the example given in 14.6.5 implies that the potential error in
>this function must not be diagnosed, because bogus<X>::fun could be valid
>for some X, and thus it should be diagnosed only if bogus<int>::fun is
>actually instantiated. (You get a similar wrong result if you instantiate
>bogus on a class type, e.g. "struct A {}; bogus<A> x;".)
>

does anyone have a work around for this (rather gigantic) bug?


i'm looking for something that will allow me to continue using vc++5
and touch as little existing (correctly written) code as possible.

so, far, for my purposes, i've got two solutions (but, i'm still not
happy with either).

class A {
...
operator int () { return 0; } // add when needed for vc5
...
};

or, as has been suggested:

inline bool operator < (const struct A&, const struct A&) { return false; }
inline bool operator == (const struct A&, const struct A&) { return false; }

anyone have a better idea?

thanks,
scott


Frank Hileman

unread,
Mar 25, 1997, 3:00:00 AM3/25/97
to

Here is the response to similar question posted to MS support. Ifdef-ing
out some template functions in <xutility> may be a better solution.

-------------------------------------------------------------------
Thanks for the question about needing to define operators < and == for
objects placed in STL containers. This is a bug in the VC 5.0 C++
compiler (not the STL headers). It was created in trying to be compliant
with the ANSI draft for C++ in a related area of compilation. I
currently have no word on when this will be fixed.

I recommend that you add global operators for the class types you are
placing in STL containers. This isn't that much work even for more than
a few types. For example:

#if (_MSC_VER == 1100)
#define GLOBAL_OPS(Type) \
bool operator < (const Type & lhs, const Type & rhs) {return true;}
\
bool operator == (const Type & lhs, const Type & rhs) {return true;}

GLOBAL_OPS(Shape)
GLOBAL_OPS(Picture)
#endif


Larry Brasfield

unread,
Mar 26, 1997, 3:00:00 AM3/26/97
to

This is slightly dangerous. Improvement below.

Frank Hileman <fran...@pacbell.net> wrote in article
<01bc39b0$d3e8adc0$591068cf@hileman1>...

bool operator < (const Type & lhs, const Type & rhs); \
bool operator == (const Type & lhs, const Type & rhs);
#else
#define GLOBAL_OPS(Type)
#endif

...

The reason this is better is that if somebody changes the usage
of the contained class(es) so as to actually need the comparison
operators, then they will get a link error instead of useless or
incorrect behavior. There is no need to actually define those
operators; it is enough to just declare them.

--
-- Larry Brasfield
The aforementioned views are mine alone.


Scott Cranton

unread,
Mar 26, 1997, 3:00:00 AM3/26/97
to

Actually you don't need to define the operator functions, just declare
them. This fools the compiler so that it compiles everything, but if the
operator is actually used, which will do the wrong thing, you will get a
linker error. This is a little safer because typically the < and ==
operators don't make sense for these classes, which is why they weren't
defined in the first place.

class foo
{ ... };

// not defined
bool operator<(const foo&, const foo&);
bool operator==(const foo&, const foo&);

Scott

Doug Harrison

unread,
Mar 29, 1997, 3:00:00 AM3/29/97
to

On 29 Mar 1997 01:08:54 GMT, "Joseph M. O'Leary"
<jmol...@earthlink.net> wrote:

>Microsoft clearly states that VC 5.0 does not support member templates.
>Thus the "problem" with the VC 5.0 STL implementation is actually a
>deficency in the compiler, not the STL code.

How is the lack of member template support relevant to this problem?

--
Doug Harrison
dHar...@worldnet.att.net

Joseph M. O'Leary

unread,
Mar 29, 1997, 3:00:00 AM3/29/97
to


Doug Harrison <dHar...@worldnet.att.net> wrote in article
<333e74fd...@netnews.worldnet.att.net>...

In the last post that was talking about this, they quoted out of the ANSI
C++ Committee Draft as follows:

14.7.1 Implicit instantiation

7 An implementation shall not implicitly instantiate a function, non-
virtual member function, class or member template that does not
require instantiation. It is unspecified whether or not an implemen-
tation implicitly instantiates a virtual member function that does not
require specialization.

But a compiler that does not support support member templates cannot
(correct me if I'm wrong) follow this rule. Thus the Microsoft STL
implementation would have to have been written to get around this compiler
deficency.

By the way, I am not positing this as if I were an expert and gladly
welcome correction.

Joe O'

Dan Muller

unread,
Mar 29, 1997, 3:00:00 AM3/29/97
to

In article <01bc3bde$1e4de090$14552399@caffeine>, jmol...@earthlink.net
says...

> Microsoft clearly states that VC 5.0 does not support member templates.
> Thus the "problem" with the VC 5.0 STL implementation is actually a
> deficency in the compiler, not the STL code.
>
> Still, it really annoys me too.

This thread had nothing to do with member templates. It's about the
unneeded instantiation of (non-template) members of class templates.

But, the lack of member templates really annoys me, too. <g>

Dan Muller

unread,
Mar 29, 1997, 3:00:00 AM3/29/97
to

In article <01bc3c8a$56f8f180$51552399@caffeine>, jmol...@earthlink.net
says...

>
>
> Doug Harrison <dHar...@worldnet.att.net> wrote in article
> <333e74fd...@netnews.worldnet.att.net>...
> > On 29 Mar 1997 01:08:54 GMT, "Joseph M. O'Leary"
> > <jmol...@earthlink.net> wrote:
> >
> > >Microsoft clearly states that VC 5.0 does not support member templates.
> > >Thus the "problem" with the VC 5.0 STL implementation is actually a
> > >deficency in the compiler, not the STL code.
> >
> > How is the lack of member template support relevant to this problem?
> >
> > --
> > Doug Harrison
> > dHar...@worldnet.att.net
>
> In the last post that was talking about this, they quoted out of the ANSI
> C++ Committee Draft as follows:
>
> 14.7.1 Implicit instantiation
>
> 7 An implementation shall not implicitly instantiate a function, non-
> virtual member function, class or member template that does not
> require instantiation. It is unspecified whether or not an implemen-
> tation implicitly instantiates a virtual member function that does not
> require specialization.
>
> But a compiler that does not support support member templates cannot
> (correct me if I'm wrong) follow this rule. Thus the Microsoft STL
> implementation would have to have been written to get around this compiler
> deficency.

Yes it can, completely. Quoting from the above, it can (but VC++ 5.0 does
not) fulfill it with respect to "function, non-virtual member function,
..." and " ... class ..." members. If you have a sense of (geek) humor,
it can even support the clause with respect to member templates, since a
compiler that doesn't support them can't instantiate them under any
circumstances!



> By the way, I am not positing this as if I were an expert and gladly
> welcome correction.

Done. But I don't consider myself an expert either, especially with
on standard legalese.

Joseph M. O'Leary

unread,
Mar 29, 1997, 3:00:00 AM3/29/97
to

Microsoft clearly states that VC 5.0 does not support member templates.
Thus the "problem" with the VC 5.0 STL implementation is actually a
deficency in the compiler, not the STL code.

Still, it really annoys me too.

Joe O'

Dan Muller <da...@ziplink.net> wrote in article

<MPG.d9f89802...@news.ziplink.net>...


> [This followup was posted to microsoft.public.vc.language and a copy was
> sent to the cited author.]
>
> In article <01bc3709$165b3240$5211eac2@mogens>, Moge...@dk-online.dk
> says...
> > It is NOT compliant to the ANSI C++ Commite Draft to require operators
> > referenced
> > by not used member functions to be implemented. Not used member
functions
> > should not be compiled, and need not be compileable!
>
> Mogen, I went back and looked at the draft in more detail. We are both
> right, but you're a lot more right than I was. :-) The situation is
> different for implicit and explicit instantiation, but I didn't
> understand what constitutes implicit instantiation for a class template
> until I took another long look at the draft. Here's what I think I
> learned:
>
> template <T> class A {};
> A<int> ai; // implicit instantiation
> template A<char>; // explicit instantiation
>
> In the implicit case, which is obviously the most common, member
> functions that are not used should not be instantiated:
>

> 14.7.1 Implicit instantiation
>
> 7 An implementation shall not implicitly instantiate a function, non-
> virtual member function, class or member template that does not
> require instantiation. It is unspecified whether or not an implemen-
> tation implicitly instantiates a virtual member function that does not
> require specialization.
>
>

> In the explicit case, however, *all* members must be instantiated:
>
> 14.7.2 Explicit instantiation
>
> 7 The explicit instantiation of a class template specialization implies
> the instantiation of all of its members not previously explicitly spe-
> cialized in the translation unit containing the explicit instantia-
> tion. A member class of a class template may be explicitly instanti-
> ated.
>
>
> This makes much more sense that what I thought last week. My apologies to

> anyone who was misled by any of my posts.
>
> Now I have something else to add to the list of broken template behavior
> in VC++.
>
> The above quotes are from the Dec 1996 Working Paper, which I referenced
> at the following URL:
>
> http://www.cygnus.com/misc/wp/dec96pub/
>

Dan Muller

unread,
Mar 30, 1997, 3:00:00 AM3/30/97
to

In article <01bc3d34$56ca8d40$28552399@caffeine>, jmol...@earthlink.net
says...
> I guess I took "shall not ...instantiate ...non-virtual member function" to
> mean it will not actually add the member function's declaration to the
> header file until the function is referenced. I was thinking of the
> template processing. Specifically, I meant a templated member function.
> which, like all template functions/classes, does not get created
> ("Instantiated"?) until it is referenced.

I assume that by "templated member function" you mean "member template
function". (The terminology is enough to drive ya nuts.) Yes, I know
that's what you meant. My point was that this is not what we were
discussing in the thread, because we already know that VC++ 5.0 doesn't
support these.

>
> Come to think of it, what do you call it when a compiler that supports
> member templates generates one of these member template functions (if not
> "instantiation")?

Well, that would be instantiation, too. What else would you call it?
Semantically, at least in the simple case of a member template of a
non-template class, this differs very little from instantiating a free
function template. (Member templates can't be virtual functions.)

> Anyway, getting back to the rule, Microsoft's implementation of vector does
> explicitly refer to operator< . My thinking was that since their compiler
> cannot support member templates, they cannot conditionally compile an
> operator< into the class via a template processor.

That assumes that the instantiation of class templates and of member
templates are handled similarly by the compiler. As mentioned above, I
think that instantiation of member templates is probably a lot more like
instantiating free function templates, except in the case of member
templates of class templates.

In fact, VC++ 4.x already *had* conditional instantiation of members of
class templates. However, it went too far with it. If a member of a class
template wasn't referenced, the compiler didn't do any syntactic analysis
at all. According to the draft standard, I believe that it's actually
supposed to analyze any expressions that aren't dependent on template
parameters. (I could be wrong about this. If I'm not, then I pity the
compiler engineers.)

> Since they must explicitly provide operator<, they have already
> instantiated the template function it calls (lexographical_compare) by the
> time you have created the class. And since lexographical_compare calls the
> member (or global) operator< for your class (the one you are storing in the
> vector), you must have an operator <.
>
> Again, assuming my thinking is correct here, the fact that you must provide
> some of these member functions (operator<, operator ==, whatever) it it is
> a deficency, is a really deficiency in the compiler because it does not
> support member templates. Not in the STL implementation, which just had to
> work with the compiler it was given.

This was exactly my original point, except for the bit about the member
templates. I think you're making assumptions about the compiler
implementation which are not warranted.

Joseph M. O'Leary

unread,
Mar 31, 1997, 3:00:00 AM3/31/97
to


Dan Muller <da...@ziplink.net> wrote in article

<MPG.da76ca22...@news.ziplink.net>...


> In article <01bc3c8a$56f8f180$51552399@caffeine>, jmol...@earthlink.net
> says...
> >

> > In the last post that was talking about this, they quoted out of the
ANSI
> > C++ Committee Draft as follows:
> >

> > 14.7.1 Implicit instantiation
> >
> > 7 An implementation shall not implicitly instantiate a function,
non-
> > virtual member function, class or member template that does
not
> > require instantiation. It is unspecified whether or not an
implemen-
> > tation implicitly instantiates a virtual member function that does
not
> > require specialization.
> >

> > But a compiler that does not support support member templates cannot
> > (correct me if I'm wrong) follow this rule. Thus the Microsoft STL
> > implementation would have to have been written to get around this
compiler
> > deficency.
>
> Yes it can, completely. Quoting from the above, it can (but VC++ 5.0 does

> not) fulfill it with respect to "function, non-virtual member function,
> ..." and " ... class ..." members. If you have a sense of (geek) humor,
> it can even support the clause with respect to member templates, since a
> compiler that doesn't support them can't instantiate them under any
> circumstances!

I guess I took "shall not ...instantiate ...non-virtual member function" to


mean it will not actually add the member function's declaration to the
header file until the function is referenced. I was thinking of the
template processing. Specifically, I meant a templated member function.
which, like all template functions/classes, does not get created
("Instantiated"?) until it is referenced.

Come to think of it, what do you call it when a compiler that supports


member templates generates one of these member template functions (if not
"instantiation")?

Anyway, getting back to the rule, Microsoft's implementation of vector does


explicitly refer to operator< . My thinking was that since their compiler
cannot support member templates, they cannot conditionally compile an
operator< into the class via a template processor.

Since they must explicitly provide operator<, they have already


instantiated the template function it calls (lexographical_compare) by the
time you have created the class. And since lexographical_compare calls the
member (or global) operator< for your class (the one you are storing in the
vector), you must have an operator <.

Again, assuming my thinking is correct here, the fact that you must provide
some of these member functions (operator<, operator ==, whatever) it it is
a deficency, is a really deficiency in the compiler because it does not
support member templates. Not in the STL implementation, which just had to
work with the compiler it was given.

Joe O'


Doug Harrison

unread,
Mar 31, 1997, 3:00:00 AM3/31/97
to

On 29 Mar 1997 21:42:26 GMT, "Joseph M. O'Leary"
<jmol...@earthlink.net> wrote:

>In the last post that was talking about this, they quoted out of the ANSI
>C++ Committee Draft as follows:
>
>14.7.1 Implicit instantiation
>
>7 An implementation shall not implicitly instantiate a function, non-
> virtual member function, class or member template that does not
> require instantiation. It is unspecified whether or not an implemen-
> tation implicitly instantiates a virtual member function that does not
> require specialization.
>
>But a compiler that does not support support member templates cannot
>(correct me if I'm wrong) follow this rule.

I don't understand why you think the failure to support member
templates relaxes the requirements concerning the other entities
mentioned in 14.7.1.7.

>Thus the Microsoft STL
>implementation would have to have been written to get around this compiler
>deficency.

What do you mean, exactly? Obviously, failing to support member
templates means that VC5 can't fully support the draft standard C++
library, but how is this shortcoming relevant to this problem?

--
Doug Harrison
dHar...@worldnet.att.net

Joseph M. O'Leary

unread,
Mar 31, 1997, 3:00:00 AM3/31/97
to

Dan Muller <da...@ziplink.net> wrote in article
<MPG.da8f6467...@news.ziplink.net>...

>
> This was exactly my original point, except for the bit about the member
> templates. I think you're making assumptions about the compiler
> implementation which are not warranted.

Usually I try to post here (and microsoft.public.vc.mfc) to help out others
on subjects I know very well (mainly MFC and multithreaded programming)
because I remember what a bear some of those areas were. However, STL is
certainly one of my weaker areas. I'm waaaay to used to MFC collection
classes, trying to go off them (and MFC) cold turkey.

I started posting to this thread mainly to provoke discussion and learn as
to really attempt to answer someone else's questions (my goof about global
operator< for CLSIDs a few days ago notwithstanding).
Gotta be clearer about that in the future.

And now that it has taken me 3 postings to get back to your original point,
I think I'll go get a copy of the ANSI C++ Comittee Draft.

Joe O'

Dan Muller

unread,
Apr 3, 1997, 3:00:00 AM4/3/97
to

In article <33442B...@bellsouth.net>, le...@bellsouth.net says...
> I've used vector<> in VC++ 4.2 on
> several classes without an operator<() or operator==().
>
>

Lee,
This is a bug that was introduced in 5.0. All class template members are
instantiated, regardless of whether they are used or not, which means
that elements of a vector must have declarations of operator< and
operator==.

(Strictly speaking, unused members may not be instantiated, but just
fully syntax-checked. I'm not sure about this, but others have indicated
that declarations for the operators are sufficient, without
implementations, which would indicate that no code is generated for the
unused members.)

Dan Muller

unread,
Apr 3, 1997, 3:00:00 AM4/3/97
to

In article <86009957...@optional.cts.com>, tmin...@cts.com says...
> Pardon me; I joined this discussion late, so I may be asking something
> that has already been answered. Also, I'm a little new to templates.
>
> I find that I can not write:
>
> vector<foo> MyFooVector;
>
> where foo is a class without operator< and operator==. I think it is
> because foo::operator<() and foo::operator==() are called by
> vector<foo>::operator<(). I never call vector<foo>::operator<() in
> my code (and never would, since there is no meaningful way to compare
> foo objects).
>
> Is this a compiler bug?

Yes, this is a compiler bug introduced in 5.0. Even though you never call
vector<foo>::operator<(), the compiler instantiates it.

Larry Brasfield

unread,
Apr 4, 1997, 3:00:00 AM4/4/97
to

Tony Minkoff <tmin...@cts.com> wrote in article <86009957...@optional.cts.com>...
> In article <MPG.da76ba42...@news.ziplink.net>,

> Dan Muller <da...@ziplink.net> wrote:
> >In article <01bc3bde$1e4de090$14552399@caffeine>, jmol...@earthlink.net
> >says...
> >> Microsoft clearly states that VC 5.0 does not support member templates.
> >> Thus the "problem" with the VC 5.0 STL implementation is actually a
> >> deficency in the compiler, not the STL code.
> >>
> >> Still, it really annoys me too.
> >
> >This thread had nothing to do with member templates. It's about the
> >unneeded instantiation of (non-template) members of class templates.
> >
> >But, the lack of member templates really annoys me, too. <g>
>
> Pardon me; I joined this discussion late, so I may be asking something
> that has already been answered. Also, I'm a little new to templates.
>
> I find that I can not write:
>
> vector<foo> MyFooVector;
>
> where foo is a class without operator< and operator==. I think it is
> because foo::operator<() and foo::operator==() are called by
> vector<foo>::operator<(). I never call vector<foo>::operator<() in
> my code (and never would, since there is no meaningful way to compare
> foo objects).
>
> Is this a compiler bug?

It's a defect in the STL implementation combined with the fact
that the compiler checks template definitions earlier. You can
fix it by declaring those operator methods. (They do not have
to be defined if you are not using them.)

Dan Muller

unread,
Apr 4, 1997, 3:00:00 AM4/4/97
to

In article <01bc40b0$e45b4620$cc2b2299@larrybr9>, lar...@earthlink.net
says...

> It's a defect in the STL implementation combined with the fact
> that the compiler checks template definitions earlier. You can
> fix it by declaring those operator methods. (They do not have
> to be defined if you are not using them.)

No, it's NOT a defect in the STL implementation! This is a compiler bug,
or at the very least a serious quality-of-implementation issue.
Unreferenced member functions should not be instantiated, according to
the draft standard. (Section 14.7.1, paragraph 7.) I suppose that one
could argue that a full syntax check is not necessarily the same thing as
instantiation, but this is a very poor choice of interpretation exactly
because of this problem.

Larry Brasfield

unread,
Apr 6, 1997, 4:00:00 AM4/6/97
to

Dan Muller <da...@ziplink.net> wrote in article
<MPG.daf3a345...@news.ziplink.net>...

I'm going to argue 3 points here.
1. The problem is a defect in the STL implementation, as I claimed.
2. It definitely is not a quality-of-implementation issue.
3. It may not be a compiler bug. (I may be mistaken, but I have
yet to see this argued with reference to the (almost) standard.)
A syntax and semantic constraint check is not the same as an
instantiation, is envisioned by the (almost) standard and STL,
may be conforming, and is a good idea.

In this discussion, "CDS" refers to the December 1996 C++ draft
standard recently made available for public comment.

Point 1. (defect in the STL implementation)

If you look at CDS section 23.2.4, para 2, you will see that
operator==() and operator<() are not defined as class member
functions but as stand-alone template functions. If the VC5
STL had been done that way, the problem would not exist. But
since the VC5 STL defined them as member functions, the check
problem can show up when a vector<> class is instantiated.
(This seems so obvious once the "vector" header and the CDS
are actually examined that I hesitate to argue this further.
Let me know if you disagree after examining them.)

There are excellent reasons for defining binary operators as
stand-alone template functions, having to do with maintaining
symmetry in the face of possible conversion sequences. So I
consider the member function approach to be a real defect
rather than a minor annoyance.

Point 2. (not quality-of-implementation)

I have not found "quality-of-implementation" in a dictionary,
but from the usage I have seen this term applies to what you
get from a compiler once it compiles, namely executable code
and data. If those relational operators were required to
show up in your linked image, (or maybe even in the object
files), I would call it a "quality-of-implementation issue".
But those unused member functions are never instantiated.
If you compile the following code and use dumpbin to look
at the .obj file, you will see that operator< appears but
operator== (which should not be instatiated) does not. The
same goes for vector<X>::operator<(), which, (as I stated),
can be declared to work-around the defect but need not be
defined. If an incorrect instantiation were occuring, it
would be necessary to define them, and they would consume
space in the linked image. That would be what most folks
would refer to as poor quality-of-implementation.

template< class T > class TC {
T m_t;
public:
bool operator< (const TC<T>&) const;
bool operator== (const TC<T>&) const;
};

template< class T > bool TC<T>::operator <(const TC<T>& t) const
{ return m_t < t.m_t; }

template< class T > bool TC<T>::operator ==(const TC<T>& t) const
{ return m_t == t; }

int compare(TC<int> t1, TC<int> t2)
{
if (t1 < t2)
return -1;
else if (t2 < t1)
return 1;
else
return 0;
}

Point 3. (full check is a good idea and not non-conforming)

As I show for point 2, a syntax and semantic constraint check is not
the same as an instantiation. All the arguments I have seen so far
about how VC5 is "broken" because of this problem have concentrated
on incorrect instantiation. But there is no instantiation.

If you look at the CDS section 14.6 (Name resolution), you can read:
5 Knowing which names are type names allows the syntax of every template
definition to be checked. No diagnostic shall be issued for a tem-
plate definition for which a valid specialization can be generated.
If no valid specialization can be generated for a template definition,
and that template is not instantiated, it is unspecified whether or
not an implementation is required to issue a diagnostic.

This suggests to me that, in at least some committee member's mind(s),
template syntax checking may be done at the point of definition
independent of whether the instantiation occurs.

I have read the CDS template section quite a bit without getting
a clear sense of what a "syntax" check really means. The strictest
sense of the term does not include semantic analysis, but when you
consider that syntax is not well separated from semantic analysis
in C++ and that the CDS has little to say about semantic analysis,
it is diffucult to argue that the CDS precludes checking that goes
further than mere legal syntax in the grammar sense.

However, I must concede that there might be way to construe some
of the language in the CDS to make the extent of VC5's checking
non-conforming. I have looked for this and have not seen it.
Rather than trying to argue a negative from the hundreds of
K-words in the CDS, I leave it for you (or somebody else) to
cite specific language in the CDS to support the idea that
VC5's behavior "is a compiler bug" as you assert. (In fact,
if somebody will just cite a reasonable number of relevant
paragraphs, I will make that argument myself and report the
"bug".) But bare assertions, unsupported by evidence, have no
persuasive power and I would never report a bug if I could only
cite my feelings about it.

Now, in spite of some uncertainty as to what the CDS finally
has to say on this (after sufficient interpretation), I claim
that a full semantic check of all member functions belonging
to an instantiated class is desirable behavior that promotes
the purposes of C++'s template feature.

When I design a class and write its definition, I provide a
new object type. By "type", I mean a known set of operations
that can be performed upon objects of that type with defined
meaning. The promise I make by publishing a class is "If you
instantiate an object of this type, you may perform any of a
particular, known set of operations upon it and depend upon
getting a result that is (more or less) well defined.

I believe that a template class should fulfill a similar
promise. "If you form a class with this template, you will
have a class which can be used to instantiate objects for
which a particular, known set of operations will have a
(more or less) well defined effect, provided that the
type(s) you supply as template arguments support certain
operations relied upon by the template class."

Now I am willing to concede that it might be inconvenient
sometimes, when using a template class, to be required to
provide template argument types that actually meet the
requirements imposed by the template class designer. But
this in no way diminishes my position. (My position is
consistent with and inspired by the way in which iterator
requirements are enforced in STL container templates and
algorithm templates.) I believe that robust, hierarchical
design is seriously compromised by having template clients
trying to guess which template argument properties are
"really" needed and which can be dispensed with because
the instantiated class will not be used to the full extent
of its promised capability.

In some cases, the provider of an instantiated class
object may be separated from the client, making a deferred
check (awaiting the actual use of a member) considerably
less useful than one occurring at class instantiation. If
I sell you a templated header and a DLL that can hand out
vector<MyClass> objects, where I have implemented MyClass,
you would be sorely dissappointed to discover that you had
no way to put those objects into a map<>. Of course, if I
test my product sufficiently, I might discover this defect
myself. But having my compiler tell me instead of you is
an improvement in my view. (My view includes the notion
that quality should be by design, not merely tested in.)

In the case of vector<X>, requiring that X support '<' and
'==' is desirable given that the definition of vector<>
promised support for those relational operators. The VC5
mistake was to make those operators promised capabilities
of vector<> when there is no inherent need for a vector
to support them. This is a simple factorization error in
contravention of the CDS, not a compiler bug.

Dan Muller

unread,
Apr 6, 1997, 4:00:00 AM4/6/97
to

In article <01bc422a$552acfe0$9a262299@larrybr9>, lar...@earthlink.net
says...

> Point 1. (defect in the STL implementation)

I looked at your references to the standard and I agree that the
implementation of vector<> in VC++ 5.0 does not comply with the CDS in
this regard.

> There are excellent reasons for defining binary operators as
> stand-alone template functions, having to do with maintaining
> symmetry in the face of possible conversion sequences. So I
> consider the member function approach to be a real defect
> rather than a minor annoyance.

I agree, although there are sometimes good reasons to prefer a member
function, usually having to do with access to private data members for
efficiency. (In any case, this isn't really material to the point in
question.)

> Point 2. (not quality-of-implementation)
>
> I have not found "quality-of-implementation" in a dictionary,
> but from the usage I have seen this term applies to what you
> get from a compiler once it compiles, namely executable code
> and data.

I meant it in the broader sense of usability. When there is ambiguity in
the standard (which I don't really think there is in this case), compiler
implementors get to make choices. In this case, the choice leads to a
tighter restriction than the standard calls for, thus shutting out some
programming options, or at least making them very inconvenient to use.
(Namely, the option of using template arguments that don't satisfy the
syntactic needs of unused class template members.)

> If those relational operators were required to
> show up in your linked image, (or maybe even in the object
> files), I would call it a "quality-of-implementation issue".
> But those unused member functions are never instantiated.

That depends on your definition of "instantiate". More on this later.

> If you compile the following code and use dumpbin to look
> at the .obj file, you will see that operator< appears but
> operator== (which should not be instatiated) does not. The
> same goes for vector<X>::operator<(), which, (as I stated),
> can be declared to work-around the defect but need not be
> defined. If an incorrect instantiation were occuring, it
> would be necessary to define them, and they would consume
> space in the linked image. That would be what most folks
> would refer to as poor quality-of-implementation.

No, that would clearly be an error in the compiler implementation. That's
not what I mean by a quality of implementation issue.

> Point 3. (full check is a good idea and not non-conforming)

> As I show for point 2, a syntax and semantic constraint check is not
> the same as an instantiation. All the arguments I have seen so far
> about how VC5 is "broken" because of this problem have concentrated
> on incorrect instantiation. But there is no instantiation.

> If you look at the CDS section 14.6 (Name resolution), you can read:
> 5 Knowing which names are type names allows the syntax of every template
> definition to be checked. No diagnostic shall be issued for a tem-
> plate definition for which a valid specialization can be generated.
> If no valid specialization can be generated for a template definition,
> and that template is not instantiated, it is unspecified whether or
> not an implementation is required to issue a diagnostic.

> This suggests to me that, in at least some committee member's mind(s),
> template syntax checking may be done at the point of definition
> independent of whether the instantiation occurs.

Agreed, but that's not the issue here. It would be a very good thing for
a compiler to do a syntax check prior to instantiation. The distinction
between syntax and semantics does not appear to be spelled out in the
CDS, but in compiler and language design name lookup and type checking
are generally considered to be semantic checks, not syntactic.

I think that this interpretation of syntax vs. semantics is strongly
implied here, since your quote from the CDS says "... allows the syntax
of every template definition to be checked..." (implying complete
syntactic information is available), and yet it also clearly states that
this checking can be done without any instantiation at all, in which case
the availability of the operator for arguments that are dependent on
template parameters is clearly undecidable.

What if a compiler saw this:

void do_something (int);
void do_something (double);

template <typename T>
void foo (T arg) {do_something(arg);}

This situation is analogous to the one we're discussing, except that
there's a function call (to do_something) rather than the application of
an operator to a variable of type T. The compiler obviously cannot decide
if the call to do_something is semantically valid or not, because it
can't do a name lookup to resolve the call to do_something until it knows
what the type of the argument is.

I think that this makes clear the distinction between syntax and
semantics in this area. Now, back to the issue of instantiation.

Section 14.6.2 states:

1 Inside a template, some constructs have semantics which may differ
from one instantiation to another. Such a construct depends on the
template argument. In particular, types and expressions may depend on
the type and or value of templates arguments and this determines the
context for name lookup for certain names. Expressions may be type-
dependent (on the type of a template argument) or value-dependent (on
the value of a non-type template argument). In an expression of the
form:

postfix-expression ( expression-listopt )
where the postfix-expression is an identifier, the identifer denotes a
dependent name if and only if any of the expressions in the expres-
sion-list is a type-dependent expression (_temp.dep.expr_). If an
operand of an operator is a type-dependent expression, the operator
also denotes a dependent name. Such names are unbound and are looked
up at the point of the template instantiation (_temp.point_) in both
the context of the template definition and the context of the point of
instantiation.

This makes it very clear that the name-lookup which is failing in
vector<>::operator< and vector<>::operator== should not be occurring,
because these member functions should not be instantiated. The exact
definition of "instantiation" becomes moot; if the compiler is
instantiating them but not generating code for them, it is obviously in
error; if it is not instantiating but only semantically analyzing, then
the semantic analysis should not include the lookup of dependent names.

For the sake of completeness (and because I already bothered to look it
up), take a look at the following.

In section 2.1 of the CDS, "Phases of translation", paragraph 1 includes
an enumeration of the phases. You should read the whole list to
understand it fully, but following is a key part of it:

7 White-space characters separating tokens are no longer signifi-
cant. Each preprocessing token is converted into a token.
(_lex.token_). The resulting tokens are syntactically and semanti-
cally analyzed and translated. [Note: Source files, translation
units and translated translation units need not necessarily be
stored as files, nor need there be any one-to-one correspondence
between these entities and any external representation. The
description is conceptual only, and does not specify any particu-
lar implementation. ]

8 Translated translation units and instantiation units are combined
as follows: [Note: some or all of these may be supplied from a
library. ] Each translated translation unit is examined to pro-
duce a list of required instantiations. [Note: this may include
instantiations which have been explicitly requested
(_temp.explicit_). ] The definitions of the required templates
are located. It is implementation-defined whether the source of
the translation units containing these definitions is required to
be available. [Note: an implementation could encode sufficient
information into the translated translation unit so as to ensure
the source is not required here. ] All the required instantia-
tions are performed to produce instantiation units. [Note: these
are similar to translated translation units, but contain no refer-
ences to uninstantiated templates and no template definitions. ]
The program is ill-formed if any instantiation fails.

Note that step 7 calls for syntactic and semantic analysis, but it is not
until step 8 that a translation unit is examined to determine the list of
required intantiations. This could be an error in the CDS, because it
doesn't seem that semantic analysis can be completely done until step 8,
when the final name lookup of dependent names is done as per 14.6.2.

> But bare assertions, unsupported by evidence, have no
> persuasive power and I would never report a bug if I could only
> cite my feelings about it.

Even if I were wrong (which I'm not), this criticism would be misplaced.
I don't know how long you've been following this thread, but earlier I
did post what I considered to be ample justification, quoting from the
CDS. (Perhaps I posted the details in a different thread, but I don't
think so.) My brief followup that you replied to was not intended to be a
full discussion of the issue. I never report bugs if believing that I
only have "feelings" about them.

Phillip R. Shaw

unread,
Apr 7, 1997, 3:00:00 AM4/7/97
to

From what I could tell reading the "CDS" it looks like the vectors
have templatized comparison operators, not that the items in the
containers have templatized operators.

ph...@dra.com

-------------------------------

Joseph M. O'Leary

unread,
Apr 9, 1997, 3:00:00 AM4/9/97
to

Actually, you can declare a template as a friend of a normal class. I have
done it successfully.

I think maybe you mean you cannot declare templates as friends within other
template definitions (as opposed to declaring them as friends within
non-template classese). This may be true, (I have not tested) but I don't
see why not.

All templates aside, declaring class B as a friend of class A does not
require you to actually implement class A anymore than a simple plain
forward declaration of class A requires you to implement it.. You can
compile, link, and run just fine.

You only have to implement A if you refer to it explicitly (try to
instantiate one, call one of its member functions through a pointer, etc.).

Is there a rule in the ARM that would prevent the same from being true for
friend templates declared within class templates?

Joe O'

Dan Muller <da...@ziplink.net> wrote in article

<MPG.db33efb9...@news.ziplink.net>...
> In article <33493dce...@news-s01.ca.us.ibm.net>, kus...@i.b.m.net
> says...


> > >I agree, although there are sometimes good reasons to prefer a member
> > >function, usually having to do with access to private data members for

> > >efficiency. (In any case, this isn't really material to the point in
> > >question.)
> >

> > The comparison operators should almost always be declared using global
> > functions. If they need access to private data then they can be
> > declared friends of the class.
>
> AFAIK, you cannot declare templates as friends.

Dan Muller

unread,
Apr 9, 1997, 3:00:00 AM4/9/97
to

[This followup was posted to microsoft.public.vc.language and a copy was
sent to the cited author.]

In article <01bc4481$2147b9f0$3d552399@caffeine>, jmol...@earthlink.net
says...


> Actually, you can declare a template as a friend of a normal class. I have
> done it successfully.

Oops, I was wrong. Section 14.5.3 of the standard spells it out
explicitly. Both classes and class templates can have friends which are
themselves templates.

(BTW, the fact that you did it successfully only means that the compiler
you were using supported it. That's not a very powerful argument these
days, since the handling of templates vary wildly and often differ
considerably from the latest draft.)

Dan Muller

unread,
Apr 10, 1997, 3:00:00 AM4/10/97
to

In article <334c869f...@news-s01.ca.us.ibm.net>, kus...@i.b.m.net
says...

> >AFAIK, you cannot declare templates as friends.
>
> Not sure what AFAIK means? But I'm pretty sure you can decalare
> template functions to be friends of template classes.
>
AFAIK = As Far As I Know, which wasn't very far, 'cos I was wrong. <g>

Joseph M. O'Leary

unread,
Apr 11, 1997, 3:00:00 AM4/11/97
to

That's right. I am using VC 5. I was not basing my answer on anything
out of the ARM and should have mentioned that.


Joe O'

--
Of course, that's just my opinion. I could be wrong

Dan Muller <da...@ziplink.net> wrote in article

<MPG.db5fce6d...@news.ziplink.net>...

Joseph M. O'Leary

unread,
Apr 11, 1997, 3:00:00 AM4/11/97
to

AFAIK is an acronym for "As Far As I Know"

Joe O'

Gary Kushner <kus...@i.b.m.net> wrote in article
<334c869f...@news-s01.ca.us.ibm.net>...

William E. Kempf

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

da...@ziplink.net (Dan Muller) wrote:

:In article <33493dce...@news-s01.ca.us.ibm.net>, kus...@i.b.m.net
:says...
:> >I agree, although there are sometimes good reasons to prefer a member

:> >function, usually having to do with access to private data members for
:> >efficiency. (In any case, this isn't really material to the point in
:> >question.)

:>
:> The comparison operators should almost always be declared using global


:> functions. If they need access to private data then they can be
:> declared friends of the class.

:
:AFAIK, you cannot declare templates as friends.
:
:--

Further, every book on C++ I have read has declared the friend
directive as the goto of the 90s, recommending you avoid it's use as
much as possible. What leads you to say "comparison operators should
almost always be declared using global functions"? Doesn't sound like
a valid thing to me.

-----
William E. Kempf : http://www.novia.net/~srwillrd
"Sir Willard" : mailto:srwi...@novia.net (home)
Knight of the Ascii Table :

Doug Harrison

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

On Fri, 18 Apr 1997 13:50:46 GMT, srwi...@novia.net (William E.
Kempf) wrote:

>:> The comparison operators should almost always be declared using global
>:> functions. If they need access to private data then they can be
>:> declared friends of the class.
>

>Further, every book on C++ I have read has declared the friend
>directive as the goto of the 90s, recommending you avoid it's use as
>much as possible. What leads you to say "comparison operators should
>almost always be declared using global functions"? Doesn't sound like
>a valid thing to me.

When you declare an operator as a member function of a class, the
operand on the left-hand side must be of that class's type (or one
derived from it). This is undesirable, for example, if the argument to
the operator function is of a built-in type; if 'a' is a variable of
the class type, and 'b' is an int, while you can say "a op b", you
can't say "b op a" (barring a conversion operator, which is almost
always best avoided). The only way to allow the latter is to make a
global operator function, typically of the form "X operator
op(int,const A&)".

For an example involving only class types, consider the STL map
iterator. There is a conversion from map::iterator to
map::const_iterator, but not the other way around, and one usually
isn't derived from the other. If the iterator classes define
operator== as member functions comparing their own types, and 'a' is a
const_iterator and 'b' an iterator, then while you can say "a == b",
you can't say "b == a", because there's no conversion from
const_iterator to iterator. The general workaround is to define a
global function, "bool operator==(const_iterator,const_iterator)"
(doing the same for iterator).

Frequently, the global operators described above need to be made
friends of their respective classes. This is a perfectly valid use of
the friend concept, and it does not represent any kind of design
problem. The operators are as much a part of the class interface as
any member function; they're just defined as non-members in order to
take advantage of conversions, so that the classes they work with act
as much like built-in types as possible.

--
Doug Harrison
dHar...@worldnet.att.net

Dan Muller

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to

[This followup was posted to microsoft.public.vc.language and a copy was
sent to the cited author.]

In article <33577bd5....@news.novia.net>, srwi...@novia.net
says...


> da...@ziplink.net (Dan Muller) wrote:
>
> :In article <33493dce...@news-s01.ca.us.ibm.net>, kus...@i.b.m.net
> :says...

> :> >I agree, although there are sometimes good reasons to prefer a member

> :> >function, usually having to do with access to private data members for
> :> >efficiency. (In any case, this isn't really material to the point in
> :> >question.)

> :>
> :> The comparison operators should almost always be declared using global
> :> functions. If they need access to private data then they can be
> :> declared friends of the class.

> :
> :AFAIK, you cannot declare templates as friends.
>

> Further, every book on C++ I have read has declared the friend
> directive as the goto of the 90s, recommending you avoid it's use as
> much as possible. What leads you to say "comparison operators should
> almost always be declared using global functions"? Doesn't sound like
> a valid thing to me.

William, although I appreciate your support, I actually retracted this
later -- you can in fact declare templates as friends, according to the
draft standard.

As to friend declarations in general: You should consider broadening your
reading list! The power of object-oriented designs is greatly enhanced by
building cooperating groups of classes, rather than insisting that every
class stand alone. Friend declarations are often an appropriate and
simple way of building these types of subsystems. Used indiscriminately,
of course, they can be much more harmful than gotos.

If I remember correctly, the advantage of global operators versus member
operators has to do primarily with the way that they interact with
automatic conversions. Global operators get both arguments the same way,
so they behave more uniformly in this regard. I don't remember the
specifics; hopefully someone will jump in and clarify or refute.

Chris Jones

unread,
Apr 18, 1997, 3:00:00 AM4/18/97
to Dan Muller

Dan Muller wrote:
>
> [This followup was posted to microsoft.public.vc.language and a copy was
> sent to the cited author.]
>
> In article <01bc4481$2147b9f0$3d552399@caffeine>, jmol...@earthlink.net
> says...
> > Actually, you can declare a template as a friend of a normal class. I have
> > done it successfully.
>
> Oops, I was wrong. Section 14.5.3 of the standard spells it out
> explicitly. Both classes and class templates can have friends which are
> themselves templates.
>
> (BTW, the fact that you did it successfully only means that the compiler
> you were using supported it. That's not a very powerful argument these
> days, since the handling of templates vary wildly and often differ
> considerably from the latest draft.)
>

Hello all,

Anyone been successful in getting MSVC 5 to recognize friend template
class declaration inside a template class? I use to be able to do it in
MSVC 4.x but it seems that 5 has pulled the plug on that one... Is this
a bug or a feature? :/

Any help will greatly be appreciated.

chris jones

Doug Harrison

unread,
Apr 26, 1997, 3:00:00 AM4/26/97
to

On Fri, 25 Apr 1997 19:49:33 GMT, srwi...@novia.net (William E.
Kempf) wrote:
<snip>
>The friend class construct breaks data
>hiding, and is something to be avoided in most cases (not all). I've
>read somewhere a quote by Stroustop (sp?, sorry if I got that wrong)
>stating that he wished he'd never added the friend keyword to the
>language.

In "The Design and Evolution of C++", page 53, Stroustrup has this to
say about friendship declarations:

"It is an explicit and specific part of a class declaration.
Consequently, I have never been able to see the recurring assertions
that a friend declaration "violates encapsulation" as anything but a
combination of ignorance and confusion with non-C++ terminology."

--
Doug Harrison
dHar...@worldnet.att.net

0 new messages