This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: Problems with PR 21210
"Nathan (Jasper) Myers" <ncm@codesourcery.com> writes:
| On Wed, Jun 01, 2005 at 09:37:38AM +0200, Gabriel Dos Reis wrote:
| >
| > My earlier comment did not provide an example:
| > void f(const complex<long double>&); // #1
| > void f(double); // #2
| > int main() {
| > std::complex<double> z;
| > f(z);
| > }
| >
| > Currently, this will pick #1. If we make _Complex double and
| > std::complex<double> identical, we silently break the program because
| > now we would call #2 (for a standard conversion is better than
| > user-defined conversion).
|
| We don't have any choice but to do something that most people would
| consider broken, one way or another.
Yet, a change that silently breaks the above does not read sensible to me.
| The best we can do is to choose
| something nobody would consider crazy (e.g. discarding imaginary part
| in _Complex -> std::complex<> copies.) Since we're outside the realm
| of the standard, anything is allowed; within certain limits we can do
| whatever makes sense. If what we do works out, it could be adopted
| into C++0x.
We're considering extensions here that shold help us implement the
library efficiently. I do not consider breaking existing programs
with well-defined semantics, because of clear semantics, something
that we should seriously contemplate. The chances that such a change
would get into C++0x appear very low to me.
| What limits? Our goal must have every program that compiles in both
| C99 and C++ mean the same thing. Not every C99 program need compile
| in C++, but for any given program in C99 that does not compile in C++,
| it should be obvious how to change it to a C99 program that does, and
| means the same thing. (This is similar to C++ requiring a cast in
| malloc expressions.) For a trivial example, we need not provide an
| implicit conversion from _Complex to scalar; it's not safe anyway,
| and it's easy to express that conversion explicitly in C99.
Without changing the conversion rule, one runs into ambiguity. We can
do the small change of making the conversion scalara -> __complex__
explicit in C++.
| Another limit is that some programs that may be construed to make
| sense need not be accepted, where there is any uncertainty about what
| the committee might decide.
However, we must be very careful. The primary reason why we have
three specializations is that conversion between std::complex is
implicit for value/precision preserving conversion, whereas
value/precision dropping conversions are made explicit -- contrary to
C99. C++ codes have been written against such semantics. We must not
break them. As you said earlier, as close as possible to C99, but not
closer.
__complex__ is useful and implementation detials, but we need not
complicate things for its sole support. If the view is that it is
close to std::complex, then we must make it an aggregate and must be
careful about throwing in implicit conversions.
| We can loosen the rules later to match
| what they choose, as long that doesn't actually change the meaning of
| valid programs. In practice I think this means we can say some
| constructs are ambiguous that need not be -- again, even some that
| would be valid C99.
|
| As soon as we can work out a framework for a solution, with the choice
| points identified, discussion should include interested ISO committee
| members, so we have a chance that what we do will be in C++0x.
|
| If we fail, _Complex and std::complex<> will be unrelated types, and
| it won't matter much what the semantics are -- the only path from one
| to the other would be via the component parts. (Even then, disallowing
| _Complex -> scalar conversions would probably be necessary.)
Agreed.
-- Gaby