Tricky conversions question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Old Wolf

    #1

    Tricky conversions question

    Here is a simplified version of a post I saw on another NG:

    struct Base {};
    struct Derived: Base {};

    struct ConstPtr
    {
    //operator const Derived * (); // F1
    operator const Derived * () const; // F2
    private:
    operator Derived * (); // F3
    //operator Derived * () const; // F4
    };

    int main()
    {
    ConstPtr ptr;

    const Derived * p3 = ptr;
    const Base * p4 = ptr;
    }

    GCC fails both p3 and p4, for private access.
    BCC allows p3 but fails p4 for the same reason.

    Now consider the slightly modified version, where F1 and F4 are
    un-commented.
    GCC allows p3, and gives p4 as ambiguous.
    BCC allows p3 but fails p4 for private access.

    Can someone give me an detailed explanation, w.r.t the Standard,
    of what's going on here? I've spent an hour poring over it and am
    no closer to solving it really.
    As far as I can see, p3+F2 is a standard conversion followed
    by a user-defined conversion (both of "Equal Match" status),
    and p3+F3 is a user-defined conversion followed by a standard
    conversion (both of "Equal Match" status again), so why is one
    preferred to the other?

  • Victor Bazarov

    #2
    Re: Tricky conversions question

    Old Wolf wrote:[color=blue]
    > Here is a simplified version of a post I saw on another NG:
    >
    > struct Base {};
    > struct Derived: Base {};
    >
    > struct ConstPtr
    > {
    > //operator const Derived * (); // F1
    > operator const Derived * () const; // F2
    > private:
    > operator Derived * (); // F3
    > //operator Derived * () const; // F4
    > };
    >
    > int main()
    > {
    > ConstPtr ptr;
    >
    > const Derived * p3 = ptr;
    > const Base * p4 = ptr;
    > }
    >
    > GCC fails both p3 and p4, for private access.
    > BCC allows p3 but fails p4 for the same reason.
    >
    > Now consider the slightly modified version, where F1 and F4 are
    > un-commented.
    > GCC allows p3, and gives p4 as ambiguous.
    > BCC allows p3 but fails p4 for private access.
    >
    > Can someone give me an detailed explanation, w.r.t the Standard,
    > of what's going on here? I've spent an hour poring over it and am
    > no closer to solving it really.
    > As far as I can see, p3+F2 is a standard conversion followed
    > by a user-defined conversion (both of "Equal Match" status),
    > and p3+F3 is a user-defined conversion followed by a standard
    > conversion (both of "Equal Match" status again), so why is one
    > preferred to the other?[/color]

    I may have a few minutes tomorrow to look it over a bit closer,
    but at this point I just tried the online Comeau thing and it
    failed the original code by both private accesses (like GCC) and
    lets everything fly once the F1 and F4 are uncommented.

    V


    Comment

    • Neelesh Bodas

      #3
      Re: Tricky conversions question

      Old Wolf wrote:[color=blue]
      > Here is a simplified version of a post I saw on another NG:
      >
      > struct Base {};
      > struct Derived: Base {};
      >
      > struct ConstPtr
      > {
      > //operator const Derived * (); // F1
      > operator const Derived * () const; // F2
      > private:
      > operator Derived * (); // F3
      > //operator Derived * () const; // F4
      > };
      >
      > int main()
      > {
      > ConstPtr ptr;
      >
      > const Derived * p3 = ptr;
      > const Base * p4 = ptr;
      > }
      >
      > GCC fails both p3 and p4, for private access.
      > BCC allows p3 but fails p4 for the same reason.[/color]

      C++ std 11.3p4
      When overload resolution succeeds, and the best viable function is not
      accessible (clause 11) in the context in which it is used, the program
      is illformed.

      In the current case, the overloaded resolution rules state that the
      best viable function for p3 and p4 is F3. Since F3 is private, the
      program is ill formed. Both the calls should be rejected.


      [color=blue]
      > Now consider the slightly modified version, where F1 and F4 are
      > un-commented.
      > GCC allows p3, and gives p4 as ambiguous.
      > BCC allows p3 but fails p4 for private access.[/color]


      for p3 (most of it applies to p4 also):

      C++ std 13.3.1.5p1
      Conversion functions that return a cv-qualified type are considered to
      yield the cv-unqualified version of that type for this process of
      selecting candidate functions.

      What this means is that operator const Derived*() is considered to be
      at the same level as the operator Derived*() as far as the process of
      selecting candidate functions. I am surprised (or rather, confused) on
      observing that expression involving p3 gets compiled well.


      for p4 :

      13.3.3.1p6) [Note: there is no such standard conversion; this
      derived-to-base
      Conversion exists only in the description of implicit conversion
      sequences.]

      Thus, the derived-to-base conversion is listed as one of the implicit
      conversions.
      So we have two paths to take here -

      a) ConstPtr --(operator Derived*) --> Derived* --(implicit
      conversion)--> const Base*
      b) ConstPtr --(operator const Derived*) --> const Derived* --(implicit
      conversion)--> const Base*

      And we are back to the same old issue - the first conversion step is
      ambiguous - neither is better. So there also should be a compilation
      error for p4.

      [color=blue]
      >
      > Can someone give me an detailed explanation, w.r.t the Standard,
      > of what's going on here? I've spent an hour poring over it and am
      > no closer to solving it really.[/color]

      Same here. Even now I am not sure, especially because Comeau online
      accepts the second version of the code, whereas my (imperfect?)
      analysis says that it shouldnot.

      Comment

      • Old Wolf

        #4
        Re: Tricky conversions question

        Neelesh Bodas wrote:[color=blue]
        > C++ std 13.3.1.5p1
        > Conversion functions that return a cv-qualified type are considered to
        > yield the cv-unqualified version of that type for this process of
        > selecting candidate functions.
        >
        > What this means is that operator const Derived*() is considered to be
        > at the same level as the operator Derived*() as far as the process of
        > selecting candidate functions. I am surprised (or rather, confused) on
        > observing that expression involving p3 gets compiled well.[/color]

        I interpret this section as only applying to the process of selecting
        viable functions. Once we have determined that F1,F2,F3,F4 are
        all viable functions, then this section is no longer relevant. In
        particular, it does not apply to the process of determining how
        "long" a conversion sequence is.

        [color=blue][color=green]
        >> Can someone give me an detailed explanation, w.r.t the Standard,
        >> of what's going on here? I've spent an hour poring over it and am
        >> no closer to solving it really.[/color]
        >
        > Same here. Even now I am not sure, especially because Comeau
        > online accepts the second version of the code, whereas my
        > (imperfect?) analysis says that it shouldnot.[/color]

        Hopefully Greg will step in here.. :)

        Comment

        Working...