Variable declaration or function prototype

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Andrew Ward

    Variable declaration or function prototype

    Hi All,
    Could someone please tell me why this code does not compile.

    struct A {};

    struct B {
    B(A &) {}
    };

    struct C {
    C(B &) {}
    void f() {}
    };

    void foo() {
    A a;
    C c(B(a));
    c.f();
    }

    If I change foo() to the following then it does compile:

    void foo() {
    A a;
    B b(a);
    C c(b);
    c.f();
    }

    I would have thought that you could pass the B temporary into C's
    constructor like that?

    Andy


  • White Wolf

    #2
    Re: Variable declaration or function prototype

    Andrew Ward wrote:[color=blue]
    > Hi All,
    > Could someone please tell me why this code does not compile.
    >
    > struct A {};
    >
    > struct B {
    > B(A &) {}
    > };
    >
    > struct C {
    > C(B &) {}
    > void f() {}
    > };
    >
    > void foo() {
    > A a;
    > C c(B(a));
    > c.f();
    > }
    >
    > If I change foo() to the following then it does compile:
    >
    > void foo() {
    > A a;
    > B b(a);
    > C c(b);
    > c.f();
    > }
    >
    > I would have thought that you could pass the B temporary into C's
    > constructor like that?[/color]

    You could if you did write the constructors properly:

    B(A const &);

    C(B const &);

    Temporaries cannot be bound to non-const references.

    --
    WW aka Attila


    Comment

    • Jim Fischer

      #3
      Re: Variable declaration or function prototype

      Andrew Ward wrote:[color=blue]
      > Hi All,
      > Could someone please tell me why this code does not compile.[/color]

      Unless I'm mistaken, the statement

      C c(B(a));

      is a function declaration (prototype). It declares a function named 'c'
      that is passed (by value) a class B object, and returns (by value) a
      class C object. This statement does not instantiate a class C object
      named 'c'.

      --
      Jim

      To reply by email, remove "link" and change "now.here" to "yahoo"
      jfischer_link58 09{at}now.here. com


      Comment

      • Andrew Ward

        #4
        Re: Variable declaration or function prototype


        "White Wolf" <wolof@freemail .hu> wrote in message
        news:bjodhd$70o $1@phys-news1.kolumbus. fi...[color=blue]
        > Andrew Ward wrote:[color=green]
        > > Hi All,
        > > Could someone please tell me why this code does not compile.
        > >
        > > struct A {};
        > >
        > > struct B {
        > > B(A &) {}
        > > };
        > >
        > > struct C {
        > > C(B &) {}
        > > void f() {}
        > > };
        > >
        > > void foo() {
        > > A a;
        > > C c(B(a));
        > > c.f();
        > > }
        > >
        > > If I change foo() to the following then it does compile:
        > >
        > > void foo() {
        > > A a;
        > > B b(a);
        > > C c(b);
        > > c.f();
        > > }
        > >
        > > I would have thought that you could pass the B temporary into C's
        > > constructor like that?[/color]
        >
        > You could if you did write the constructors properly:
        >
        > B(A const &);
        >
        > C(B const &);
        >
        > Temporaries cannot be bound to non-const references.
        >
        > --
        > WW aka Attila
        >
        >[/color]

        Even when I try passing by const & like you suggested it still does not
        work, the error message is:

        error C2228: left of '.f' must have class/struct/union type
        type is 'overloaded-function'

        Maybe Jim Fischer's suggestion is correct?

        Andy


        Comment

        • Kevin Goodsell

          #5
          Re: Variable declaration or function prototype

          Andrew Ward wrote:
          [color=blue]
          > "White Wolf" <wolof@freemail .hu> wrote in message
          > news:bjodhd$70o $1@phys-news1.kolumbus. fi...
          >[color=green]
          >>Andrew Ward wrote:
          >>[color=darkred]
          >>>Hi All,
          >>>Could someone please tell me why this code does not compile.
          >>>
          >>>struct A {};
          >>>
          >>>struct B {
          >>> B(A &) {}
          >>>};
          >>>
          >>>struct C {
          >>> C(B &) {}
          >>> void f() {}
          >>>};
          >>>
          >>>void foo() {
          >>> A a;
          >>> C c(B(a));
          >>> c.f();
          >>>}
          >>>
          >>>If I change foo() to the following then it does compile:
          >>>
          >>>void foo() {
          >>> A a;
          >>> B b(a);
          >>> C c(b);
          >>> c.f();
          >>>}
          >>>
          >>>I would have thought that you could pass the B temporary into C's
          >>>constructo r like that?[/color]
          >>
          >>You could if you did write the constructors properly:
          >>
          >>B(A const &);
          >>
          >>C(B const &);
          >>
          >>Temporaries cannot be bound to non-const references.
          >>
          >>--
          >>WW aka Attila
          >>
          >>[/color]
          >
          >
          > Even when I try passing by const & like you suggested it still does not
          > work, the error message is:
          >
          > error C2228: left of '.f' must have class/struct/union type
          > type is 'overloaded-function'
          >
          > Maybe Jim Fischer's suggestion is correct?
          >[/color]

          In fact, they are both correct (I think). Attila's answer is what I
          would have said. The problem Jim pointed out is a bit more insidious:

          C c(B(a));

          I don't know the exact rule, but basically because this *could* be
          either a function declaration or an object instantiation, the former
          wins. It's equivalent to

          C c(B a);

          With a pair of superfluous parenthesis.

          -Kevin
          --
          My email address is valid, but changes periodically.
          To contact me please use the address from a recent posting.

          Comment

          • Jim Fischer

            #6
            Re: Variable declaration or function prototype

            Kevin Goodsell wrote:[color=blue][color=green]
            >> Maybe Jim Fischer's suggestion is correct?
            >>[/color]
            >
            > In fact, they are both correct (I think). Attila's answer is what I
            > would have said. The problem Jim pointed out is a bit more insidious:
            >
            > C c(B(a));
            >
            > I don't know the exact rule, but basically because this *could* be
            > either a function declaration or an object instantiation, the former
            > wins. It's equivalent to
            >
            > C c(B a);
            >
            > With a pair of superfluous parenthesis.[/color]

            I'm 99.999% sure the statement 'C c(B(a));' is a function declaration
            (see: 8.2/1 in ISO 14882:1998).

            FWIW, you can disambiguate the interior subexpression 'B(a)' by wrapping
            it in parens, e.g.,

            C c( (B(a)) );

            Now the compiler treats 'B(a)' as an object declaration that uses a
            function-style type cast as the initializer (and not a function
            declaration with a redundant set of parens around a parameter name).
            IOW, 'B(a)' is now considered an invocation of B::B(A&). Consequently,
            the surrounding expression - i.e., the declaration of 'c' - is also
            treated as an object declaration with a function-style type cast as the
            initializer.

            Caveat: Making this change to your code introduces another problem.
            Specifically, the unnamed, temporary class B object that results from
            the invocation of B::B(A&) cannot be bound to a non-const reference. So
            the construction of 'c' cannot occur because class C does not have a
            suitable constructor - e.g., C::C(B&) cannot be used because B& is a
            non-const reference. There are (at least) two fixes for this problem:

            1) Modify the existing class C ctor

            C(B &) { }

            so its reference is const-valued

            C(const B &) { }

            or,

            2) Add a second ctor to class C; one with a suitable const reference
            argument:

            class C {
            C (B &) { }
            C (const B &) { }
            void f () { }
            }

            --
            Jim

            To reply by email, remove "link" and change "now.here" to "yahoo"
            jfischer_link58 09{at}now.here. com


            Comment

            • White Wolf

              #7
              Re: Variable declaration or function prototype

              Andrew Ward wrote:
              [SNIP][color=blue]
              > Even when I try passing by const & like you suggested it still does
              > not work, the error message is:
              >
              > error C2228: left of '.f' must have class/struct/union type
              > type is 'overloaded-function'
              >
              > Maybe Jim Fischer's suggestion is correct?[/color]

              Not maybe. :-) Definitely. I am ashamed not seeing it - especially because
              I have got my copy - of the book mentioning this "gotcha" - signed by the
              author. Well, well well. Time for me to look for a job where no brains are
              required. :-)

              --
              WW aka Attila


              Comment

              Working...