Topic: Who's right, me et al. or MetroWerks?
Author: Wayne Witzke <wwitzke@immersa.uky.edu>
Date: 2000/06/06 Raw View
wmm@fastdial.net wrote:
> This is an open issue on the core language issues list (#115).
> To summarize the issue, the Standard doesn't currently say
> clearly one way or the other. It's clearly possible for a
> template-id with a complete argument list to be ambiguous:
>
> template <class T> void f(T);
> template <class T> void f(T*);
>
> ... f<int> ... // which one?
>
> The question is whether it should be allowed to identify
> a particular specialization using a complete argument list
> if there is only one template of that name in scope.
>
> The argument advanced in the issue is that this ought to
> be prohibited because it leads to fragile code that will
> break if another function template of the same name is
> introduced. On the other side is convenience for cases
> like this and a moderate consistency with the handling of
> non-template functions. (You need a target type for
> taking the address of an overloaded function but not for
> a non-overloaded function.)
>
> The Committee has not yet reached consensus on the
> resolution of this issue.
I read through that issue, and I was wondering... If the resolution of that
issue is that function specializations are considered to name a set of
overloaded functions, how would you pass a template function as a parameter to
another function? Would it simply be impossible to use a template function as a
parameter to another function? That's what it sounds like to me. If a template
specilization only defines a set of overloaded functions, then you definitely
cannot take the reference of any particular function in that set... That would
seem to limit greatly the usefulness of templates, especially for a person
writing a library.
It also seems to be totally inconsistant with other parts of the standard.
14.8.1 part 2 says that "[a] template argument list may be specified when
referring to a specialization of a function template ... when the address of a
function is taken, when a function initializes a reference to function, or when
a pointer to member function is formed." In order to take the address of a
function, or initialize a reference to function, or form a pointer to member
function, when the function is a template, don't you *have* to be creating a
specific instance of the function? Otherwise, how could you take the address of
the function?
Anyway, if I'm right about 14.8.1 part 2, it seems to me that changing 13.4 part
1 would cause a significant change in the laguage specification, something that
I hear isn't suppossed to make it in as a defect report.
Any thoughts on this anyone?
Wayne
---
[ 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: wmm@fastdial.net
Date: 2000/06/06 Raw View
In a previous article, Wayne Witzke <wwitzke@immersa.uky.edu> writes:
>wmm@fastdial.net wrote:
>> This is an open issue on the core language issues list (#115).
>
>I read through that issue, and I was wondering... If the resolution of that
>issue is that function specializations are considered to name a set of
>overloaded functions, how would you pass a template function as a parameter
to
>another function? Would it simply be impossible to use a template function
as a
>parameter to another function? That's what it sounds like to me. If a
template
>specilization only defines a set of overloaded functions, then you
definitely
>cannot take the reference of any particular function in that set... That
would
>seem to limit greatly the usefulness of templates, especially for a person
>writing a library.
No -- in most contexts, the type of the target of the conversion
or reference binding allows you to do overload resolution to pick
a particular specialization. For instance,
template <class T> void f(T);
void g(void (*fp)(int));
void x() {
g(f); // f<int>(int), by deduction
g(f<int>); // ditto
}
Because you know that only a function matching "void (*)(int)"
is acceptable as an argument for "g", you can do template argument
deduction on "f" and get the correct specialization. (See 13.4.)
The problem arises if "g" is a function template. In that case,
you are trying to do template argument deduction for "g" from
the argument that is specified in the call; consequently, the
context doesn't give you a target type to specialize "f". The
issue is whether explicitly writing a template-id for "f"
(e.g., "f<int>") is sufficient. It clearly is not sufficient
if there is more than one "f" in scope. It's not clear whether
it should be if there is only one "f", and that's the issue.
>It also seems to be totally inconsistant with other parts of the standard.
>14.8.1 part 2 says that "[a] template argument list may be specified when
>referring to a specialization of a function template ... when the address of
a
>function is taken, when a function initializes a reference to function, or
when
>a pointer to member function is formed." In order to take the address of a
>function, or initialize a reference to function, or form a pointer to member
>function, when the function is a template, don't you *have* to be creating a
>specific instance of the function? Otherwise, how could you take the address
of
>the function?
Yes, and if the target of the conversion/reference binding gives
you the required type, there's no problem.
-- William M. Miller
----- Posted via NewsOne.Net: Free Usenet News via the Web -----
----- http://newsone.net/ -- Discussions on every subject. -----
NewsOne.Net prohibits users from posting spam. If this or other posts
made through NewsOne.Net violate posting guidelines, email abuse@newsone.net
---
[ 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: Wayne Witzke <wwitzke@immersa.uky.edu>
Date: 2000/06/06 Raw View
wmm@fastdial.net wrote:
> No -- in most contexts, the type of the target of the conversion
> or reference binding allows you to do overload resolution to pick
> a particular specialization. For instance,
>
> template <class T> void f(T);
> void g(void (*fp)(int));
> void x() {
> g(f); // f<int>(int), by deduction
> g(f<int>); // ditto
> }
>
> Because you know that only a function matching "void (*)(int)"
> is acceptable as an argument for "g", you can do template argument
> deduction on "f" and get the correct specialization. (See 13.4.)
>
> The problem arises if "g" is a function template. In that case,
> you are trying to do template argument deduction for "g" from
> the argument that is specified in the call; consequently, the
> context doesn't give you a target type to specialize "f". The
> issue is whether explicitly writing a template-id for "f"
> (e.g., "f<int>") is sufficient. It clearly is not sufficient
> if there is more than one "f" in scope. It's not clear whether
> it should be if there is only one "f", and that's the issue.
>
> >It also seems to be totally inconsistant with other parts of the standard.
> >14.8.1 part 2 says that "[a] template argument list may be specified when
> >referring to a specialization of a function template ... when the address of
> a
> >function is taken, when a function initializes a reference to function, or
> when
> >a pointer to member function is formed." In order to take the address of a
> >function, or initialize a reference to function, or form a pointer to member
> >function, when the function is a template, don't you *have* to be creating a
> >specific instance of the function? Otherwise, how could you take the address
> of
> >the function?
>
> Yes, and if the target of the conversion/reference binding gives
> you the required type, there's no problem.
I think I see now. The lack of a specific destination type in a template
function makes it potentially ambiguous to use a specialized template function
as a parameter, and the reasoning behind the issue is rather than accept the
exceptional(?) circumstance when the template arguments completely describe the
function, a circumstance that could easily change, the possibility should simply
not exist. Is that right?
Then, what mechanisms would there be to pass an instance of a template function
to another template function?
Thank you for your help :-)
Wayne
---
[ 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: wmm@fastdial.net
Date: 2000/06/06 Raw View
In article <393BBFB8.3197550@immersa.uky.edu>,
wwitzke@immersa.uky.edu wrote:
> Scott, I looked at the standard, and I think MetroWerks skipped a few
parts of
> the standard. In 14.8.1 parts 1 and 2, it seems to cover this
circumstance
> pretty clearly. In part 1 it says:
>
> "Template arguments can be specified when referring to a function
template
> specialization by qualifying the function template name with the list
of
> template-arguments in the same way as template-arguments are
specified in uses
> of a class template specialization."
>
> I believe that says that you can use a syntax like the following:
>
> funct<arg1, arg2, ..., argn>
There's no question about this.
> In part 2 the standard says:
>
> "A template list may be specified when referring to a specialization
of a
> function template
>
> -- when a function is called,
>
> -- when the address of a function is taken, when a function
initializes a
> reference to function, or when a pointer to member function is formed,
>
> -- in an explicit specialization,
>
> -- in an explicit instantiation, or
>
> -- in a friend declaration.
>
> Trailing template arguments that can be deduced (14.8.2) may be
omitted from the
> list of explicit template-arguments. If all of the template
arguments can be
> deduced, they may all be omitted; in this case, the empty template
argument list
> <> itself may also be omitted."
>
> The second instance when a template argument list may be specified
seems to
> cover the circumstance that you gave up above. When you pass
>
> average<iterator_traits<II1>::value_type>
>
> to the transform function, I assume that it must be taking a
reference to the
> function, and part two specifically states that an template arguments
may be
> explicitly specified when a reference to a function is initialized
with the
> template function. Based on this alone it seems to me that
MetroWerks is
> misintrepreting the standard.
The problem is initializing a reference or converting to a
pointer is normally done in the context of a target type, so
you have types from which the template argument deduction can
work. In this case, you are attempting to determine the type
of the function argument (for template argument deduction on
the called function), so there's no context for doing argument
deduction on the specialization being passed as a function
argument.
What you've said so far is in the context of template
argument deduction. As mentioned in the citation from 14.8.1p2,
you can omit deduced arguments, so evidently the context is
deduction. As I mentioned in my preceding post, it's obvious
that full specification of template arguments is not enough to
eliminate the need for argument deduction in the general case,
e.g.,
template <class T> void f(T);
template <class T> void f(int, T);
template <class T> void g(T);
void x() {
g(f<int>); // ambiguous: which f?
}
There's nothing in the Standard that says, either way, whether
you can skip the need for deduction if there happens to be
only one template named "f" in scope and you've explicitly
specified all the needed template arguments. That would be a
special case, and the Standard just doesn't describe what
happens for that special case.
> I see nothing in 18.4.2 that would contradict this, and I even
noticed in
> 14.8.2.4, part 3 that the standard says:
>
> "In most cases, the types, templates, and non-type values that are
used to
> compose P [a type that is specified in terms of template parameters --
14.8.2.4
> part 1] participate in template argument deduction. That is, they
may be used
> to determine the value of a template argument, and the value so
determined must
> be consistent with the values determined elsewhere. In certain
contexts,
> however, the value does not participate in type deduction, but
instead uses the
> values of template arguments that were either deduced elsewhere or
*explicitly
> specified*. If a template parameter is used only in nondeduced
contexts and is
> not *explicitly specified*, template argument deduction fails."
>
> That seems to indicate that the type deduction rules for a template
parameter do
> not actually have to be followed if the template argument was
explicitly
> specified. Or, probably more accurate, it indicates that type
deduction is
> exceptionally easy if a template argument was specifically supplied
and that
> additional information that might be used to deduce a type need not
be provided
> (and will not be considered if it is provided).
No, what's being described here is how template parameters
used in nondeduced contexts are handled. In a number of
places (described immediately following the citation you gave),
using a template parameter does not allow the compiler to
deduce the parameter from the supplied argument type, and this
passage simply says that the parameter must be deducible from
some other use or it must be explicitly specified. It has
nothing to do with the question at hand -- in other words,
it's talking about cases where you _must_ give explicit
template arguments, not relaxing the requirements on argument
deduction in the context of explicit template arguments.
--
William M. Miller, wmm@fastdial.net
OnDisplay, Inc. (www.ondisplay.com)
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ 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: Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
Date: 2000/06/06 Raw View
Wayne Witzke <wwitzke@immersa.uky.edu> writes:
[...]
| I read through that issue, and I was wondering... If the resolution of that
| issue is that function specializations are considered to name a set of
| overloaded functions, how would you pass a template function as a parameter to
| another function?
You can use static_cast<> to disambiguate.
| ... Would it simply be impossible to use a template function as a
| parameter to another function? That's what it sounds like to me. If a template
| specilization only defines a set of overloaded functions,
I think the point here is that a template-id does not suffice to name
unambiguously a function template specialization as that
specialization could have been overloaded. Class types do not suffer
from overloading.
| ... then you definitely
| cannot take the reference of any particular function in that set... That would
| seem to limit greatly the usefulness of templates, especially for a person
| writing a library.
Notice that using non-pointer function objects does not carry that bag
of problems because types can't be overloaded (so no argument
deduction trouble).
| It also seems to be totally inconsistant with other parts of the standard.
| 14.8.1 part 2 says that "[a] template argument list may be specified when
| referring to a specialization of a function template ... when the address of a
| function is taken, when a function initializes a reference to function, or when
| a pointer to member function is formed." In order to take the address of a
| function, or initialize a reference to function, or form a pointer to member
| function, when the function is a template, don't you *have* to be creating a
| specific instance of the function?
In short, yes.
| ... Otherwise, how could you take the address of
| the function?
As you would have done it for a non template function.
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ 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: Matt Austern <austern@sgi.com>
Date: 2000/06/06 Raw View
smeyers@aristeia.com (Scott Meyers) writes:
> Consider the following code, where the interesting line is flagged:
>
> template<typename FloatingPointType>
> FloatingPointType average(FloatingPointType val1, FloatingPointType val2)
> {
> return (val1 + val2) / 2;
> }
>
> template<typename II1, typename II2>
> void writeAverages(II1 begin1, II1 end1, II2 begin2, std::ostream& s)
> {
> using namespace std;
>
> transform(begin1, end1, begin2,
> ostream_iterator<iterator_traits<II1>::value_type>(s, " "),
> average<iterator_traits<II1>::value_type> /* !!! */
> );
> }
Irrespective of the things that other people have been discussing,
aren't the "/* !!! */" line, and the one above it, both wrong?
Both lines use "iterator_traits<II1>::value_type" as a template
argument. This is a qualified name, and it depends on the template
parameter II1, and (14.6/3) "A qualified-name that refers to a type
and that depends on a template-parameger shall be prefixed by the
keyword typename to indicate that the qualified-name denotes a type."
---
[ 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: smeyers@aristeia.com (Scott Meyers)
Date: 2000/06/06 Raw View
On Tue, 6 Jun 2000 02:36:06 CST, wmm@fastdial.net wrote:
> This is an open issue on the core language issues list (#115).
Thanks for the clarification.
Scott
---
[ 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: wmm@fastdial.net
Date: 2000/06/07 Raw View
In article <393C1BE0.E86D237F@immersa.uky.edu>,
wwitzke@immersa.uky.edu wrote:
>
> I think I see now. The lack of a specific destination type in a
template
> function makes it potentially ambiguous to use a specialized template
function
> as a parameter, and the reasoning behind the issue is rather than
accept the
> exceptional(?) circumstance when the template arguments completely
describe the
> function, a circumstance that could easily change, the possibility
should simply
> not exist. Is that right?
That is the argument made in issue #115. As I said, the Committee
has not reached any decision one way or the other.
> Then, what mechanisms would there be to pass an instance of a
template function
> to another template function?
As Gabriel dos Reis mentioned, you can use an explicit cast to
the appropriate type, or you could write a non-template forwarding
function. For instance:
template <class T> void f(T);
template <class T> void g(T);
void x() {
g((void(*)(int)) f); // cast selects f<int>
}
--
William M. Miller, wmm@fastdial.net
OnDisplay, Inc. (www.ondisplay.com)
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ 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: smeyers@aristeia.com (Scott Meyers)
Date: 2000/06/05 Raw View
Consider the following code, where the interesting line is flagged:
template<typename FloatingPointType>
FloatingPointType average(FloatingPointType val1, FloatingPointType val2)
{
return (val1 + val2) / 2;
}
template<typename II1, typename II2>
void writeAverages(II1 begin1, II1 end1, II2 begin2, std::ostream& s)
{
using namespace std;
transform(begin1, end1, begin2,
ostream_iterator<iterator_traits<II1>::value_type>(s, " "),
average<iterator_traits<II1>::value_type> /* !!! */
);
}
Note that the function object passed to transform() is a specific instance
of the function template average. I think this is legit. MSVC thinks it's
legit. g++ thinks it's legit. Borland 5.5 thinks it's legit. MWCW
rejects it, and the people at MW reason as follows:
A function template name plus an explicit argument list is not a function
template specialization, it still has to go through the argument
deduction process that is specified in 14.8.2 when it is used in a
function call. So I don't think it should be treated as a function
template specialization in the context of a template function argument.
Who's right, me (with supporting friend-of-the-geek briefs from Microsoft,
Gnu, and Borland) or MetroWerks?
Thanks,
Scott
--
"Effective STL" Seminar June 7-9 Portland, Oregon
Details at http://www.trekservices.com/estl/
---
[ 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: Wayne Witzke <wwitzke@immersa.uky.edu>
Date: 2000/06/06 Raw View
Scott Meyers wrote:
>
> Consider the following code, where the interesting line is flagged:
>
> template<typename FloatingPointType>
> FloatingPointType average(FloatingPointType val1, FloatingPointType val2)
> {
> return (val1 + val2) / 2;
> }
>
> template<typename II1, typename II2>
> void writeAverages(II1 begin1, II1 end1, II2 begin2, std::ostream& s)
> {
> using namespace std;
>
> transform(begin1, end1, begin2,
> ostream_iterator<iterator_traits<II1>::value_type>(s, " "),
> average<iterator_traits<II1>::value_type> /* !!! */
> );
> }
>
> Note that the function object passed to transform() is a specific instance
> of the function template average. I think this is legit. MSVC thinks it's
> legit. g++ thinks it's legit. Borland 5.5 thinks it's legit. MWCW
> rejects it, and the people at MW reason as follows:
>
> A function template name plus an explicit argument list is not a function
> template specialization, it still has to go through the argument
> deduction process that is specified in 14.8.2 when it is used in a
> function call. So I don't think it should be treated as a function
> template specialization in the context of a template function argument.
>
> Who's right, me (with supporting friend-of-the-geek briefs from Microsoft,
> Gnu, and Borland) or MetroWerks?
Scott, I looked at the standard, and I think MetroWerks skipped a few parts of
the standard. In 14.8.1 parts 1 and 2, it seems to cover this circumstance
pretty clearly. In part 1 it says:
"Template arguments can be specified when referring to a function template
specialization by qualifying the function template name with the list of
template-arguments in the same way as template-arguments are specified in uses
of a class template specialization."
I believe that says that you can use a syntax like the following:
funct<arg1, arg2, ..., argn>
In part 2 the standard says:
"A template list may be specified when referring to a specialization of a
function template
-- when a function is called,
-- when the address of a function is taken, when a function initializes a
reference to function, or when a pointer to member function is formed,
-- in an explicit specialization,
-- in an explicit instantiation, or
-- in a friend declaration.
Trailing template arguments that can be deduced (14.8.2) may be omitted from the
list of explicit template-arguments. If all of the template arguments can be
deduced, they may all be omitted; in this case, the empty template argument list
<> itself may also be omitted."
The second instance when a template argument list may be specified seems to
cover the circumstance that you gave up above. When you pass
average<iterator_traits<II1>::value_type>
to the transform function, I assume that it must be taking a reference to the
function, and part two specifically states that an template arguments may be
explicitly specified when a reference to a function is initialized with the
template function. Based on this alone it seems to me that MetroWerks is
misintrepreting the standard.
I see nothing in 18.4.2 that would contradict this, and I even noticed in
14.8.2.4, part 3 that the standard says:
"In most cases, the types, templates, and non-type values that are used to
compose P [a type that is specified in terms of template parameters -- 14.8.2.4
part 1] participate in template argument deduction. That is, they may be used
to determine the value of a template argument, and the value so determined must
be consistent with the values determined elsewhere. In certain contexts,
however, the value does not participate in type deduction, but instead uses the
values of template arguments that were either deduced elsewhere or *explicitly
specified*. If a template parameter is used only in nondeduced contexts and is
not *explicitly specified*, template argument deduction fails."
That seems to indicate that the type deduction rules for a template parameter do
not actually have to be followed if the template argument was explicitly
specified. Or, probably more accurate, it indicates that type deduction is
exceptionally easy if a template argument was specifically supplied and that
additional information that might be used to deduce a type need not be provided
(and will not be considered if it is provided).
In either case, I don't think that MetroWerks' argument holds any water. I
think they might have misread their copy of the standard, or else they have an
old working copy that is now out of date.
Hope this helps!
Wayne
---
[ 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: wmm@fastdial.net
Date: 2000/06/06 Raw View
In article <MPG.13a2ec253ce070959896f8@news.supernews.com>,
smeyers@aristeia.com (Scott Meyers) wrote:
> Consider the following code, where the interesting line is flagged:
>
> template<typename FloatingPointType>
> FloatingPointType average(FloatingPointType val1, FloatingPointType
val2)
> {
> return (val1 + val2) / 2;
> }
>
> template<typename II1, typename II2>
> void writeAverages(II1 begin1, II1 end1, II2 begin2, std::ostream&
s)
> {
> using namespace std;
>
> transform(begin1, end1, begin2,
> ostream_iterator<iterator_traits<II1>::value_type>
(s, " "),
> average<iterator_traits<II1>::value_type> /* !!! */
> );
> }
>
> Note that the function object passed to transform() is a specific
instance
> of the function template average. I think this is legit. MSVC
thinks it's
> legit. g++ thinks it's legit. Borland 5.5 thinks it's legit. MWCW
> rejects it, and the people at MW reason as follows:
>
> A function template name plus an explicit argument list is not a
function
> template specialization, it still has to go through the argument
> deduction process that is specified in 14.8.2 when it is used in a
> function call. So I don't think it should be treated as a function
> template specialization in the context of a template function
argument.
>
> Who's right, me (with supporting friend-of-the-geek briefs from
Microsoft,
> Gnu, and Borland) or MetroWerks?
This is an open issue on the core language issues list (#115).
To summarize the issue, the Standard doesn't currently say
clearly one way or the other. It's clearly possible for a
template-id with a complete argument list to be ambiguous:
template <class T> void f(T);
template <class T> void f(T*);
... f<int> ... // which one?
The question is whether it should be allowed to identify
a particular specialization using a complete argument list
if there is only one template of that name in scope.
The argument advanced in the issue is that this ought to
be prohibited because it leads to fragile code that will
break if another function template of the same name is
introduced. On the other side is convenience for cases
like this and a moderate consistency with the handling of
non-template functions. (You need a target type for
taking the address of an overloaded function but not for
a non-overloaded function.)
The Committee has not yet reached consensus on the
resolution of this issue.
--
William M. Miller, wmm@fastdial.net
OnDisplay, Inc. (www.ondisplay.com)
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ 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 ]