Movatterモバイル変換


[0]ホーム

URL:


Issue 84 - WG21 CWG Issues
Title
Overloading and conversion loophole used by auto_ptr
Status
tc1
Section
12.2.4.2 [over.best.ics]
Submitter
Steve Adamczyk

Created on1998-12-10.00:00:00 last changed277 months ago

Messages

msg317 (view)
Date: 2000-10-15.00:00:00

Proposed resolution (10/00):

Change 12.2.4.2 [over.best.ics] paragraphs 3 and 4 from

Except in the context of an initialization by user-definedconversion (12.2.2.5 [over.match.copy],12.2.2.6 [over.match.conv]), a well-formed implicit conversionsequence is one of the following forms:

In the context of an initialization by user-defined conversion (i.e.,when considering the argument of a user-defined conversion function;see 12.2.2.5 [over.match.copy], 12.2.2.6 [over.match.conv]),only standard conversion sequences andellipsis conversion sequences are allowed.

to

A well-formed implicit conversionsequence is one of the following forms:

However, when considering the argument of a user-defined conversionfunction that is a candidate by 12.2.2.4 [over.match.ctor]when invoked for the copyingof the temporary in the second step of a class copy-initialization, orby 12.2.2.5 [over.match.copy], 12.2.2.6 [over.match.conv],or 12.2.2.7 [over.match.ref] in all cases, only standardconversion sequences and ellipsis conversion sequences areallowed.

msg153 (view)
Date: 2022-02-18.07:47:23

By the letter of the standard, the conversions required tomakeauto_ptr work should be accepted.

However, there's good reason to wonder if there isn't a bug in the standardhere. Here's the issue: line 16 in the example below comes down to

copy-initialize anauto_ptr<Base> fromanauto_ptr<Derived> rvalue
To do that, we first look to see whether we can convertanauto_ptr<Derived>to anauto_ptr<Base>, by enumerating theconstructors ofauto_ptr<Base>and the conversion functions ofauto_ptr<Derived>.There's a single possible way to do the conversion, namely the conversionfunction

    auto_ptr<Derived>::operator auto_ptr<Base>()
(generated from the template). (The constructorauto_ptr<Base>(auto_ptr_ref<Base>)doesn't work because it requires a user-defined conversion on theargument.)

So far, so good. Now, we do the copy step:

direct-initialize anauto_ptr<Base>from anauto_ptr<Base>rvalue
This, as we've gone to great lengths to set up, is done by callingthe conversion function
    auto_ptr<Base>::operator auto_ptr_ref<Base>()
(generated from the template), and then the constructor
    auto_ptr<Base>(auto_ptr_ref<Base>)
(generated from the template).

The problem with this interpretation is that it violates the long-standingcommon-law rule that only a single user-defined conversion will be calledto do an implicit conversion. I find that pretty disturbing.(In fact, the full operation involves two conversion functions and twoconstructors, but "copy" constructors are generally considered not to beconversions.)

The direct-initialization second step of a copy-initialization was intendedto be a simple copy — you've made a temporary, and now you use a copyconstructor to copy it. Because it is defined in terms of directinitialization, however, it can exploit the loophole that auto_ptris based on.

To switch to personal opinion for a second, I think it's bad enoughthat auto_ptr has to exploit a really arcane loophole of overload resolution,but in this case it seems like it's exploiting a loophole on a loophole.

    struct Base {                             //  2       static void sink(auto_ptr<Base>);      //  3    };                                        //  4    struct Derived : Base {                   //  5       static void sink(auto_ptr<Derived>);   //  6    };                                        //  7    auto_ptr<Derived> source() {              //  8       auto_ptr<Derived> p(source());         //  9       auto_ptr<Derived> pp(p);               // 10       Derived::sink(source());               // 11       p = pp;                                // 12       p = source();                          // 13       auto_ptr<Base> q(source());            // 14       auto_ptr<Base> qp(p);                  // 15       Base::sink(source());                  // 16       q = pp;                                // 17       q = source();                          // 18       return p;                              // 19       return source();    }
Derek Inglis:

It seems clear to me that the result of this direct initilizationmust be the second standard conversion sequence in a user definedconversion sequence. Otherwise the resulting conversion sequence isnot an implicit conversion sequence. By the letter of the standard,the sequence of conversions making up a copy-initialization must be animplicit conversion sequence.

Paragraph 3 of 7.3 [conv]:

An expressione can beimplicitly converted to a typeT if and only if the declaration "T t=e;" iswell-formed, for some invented temporary variablet(9.5 [dcl.init]).

Paragraph 1 of 12.2.4.2 [over.best.ics]:

Animplicit conversion sequence is a sequence of conversionsused to convert an argument in a function call to the type of thecorresponding parameter of the function being called. The sequence ofconversions is an implicit conversion as defined in7.3 [conv], which means it is governed by the rules forinitialization of an object or reference by a single expression(9.5 [dcl.init], 9.5.4 [dcl.init.ref]).
Sentence 1 of paragraph 12 of 9.5 [dcl.init]:
The initialization that occurs in argument passing ...is calledcopy-initialization and is equivalent to the form
     T x = a;

For me, these sentences imply that all sequences of conversionspermitted on a function argument must be valid implicit conversionsequences.

The 'loophole' can be closed by adding a sentence (or note) to thesection describing the 'direct initialization second step of a copyinitialization' stating that the copy initialization is ill-formed ifthe conversion sequence resulting from the direct initialization isnot a standard conversion sequence.

(See alsoissue 177 and paperJ16/00-0009 = WG21 N1232.)

History
DateUserActionArgs
2003-04-25 00:00:00adminsetstatus: dr -> tc1
2000-11-18 00:00:00adminsetstatus: ready -> dr
2000-05-21 00:00:00adminsetmessages: +msg317
2000-05-21 00:00:00adminsetstatus: open -> ready
1998-12-10 00:00:00admincreate

[8]ページ先頭

©2009-2026 Movatter.jp