Variable declaration or function prototype

Discussion in 'C++' started by Andrew Ward, Sep 11, 2003.

  1. Andrew Ward

    Andrew Ward Guest

    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
     
    Andrew Ward, Sep 11, 2003
    #1
    1. Advertising

  2. Andrew Ward

    White Wolf Guest

    Andrew Ward wrote:
    > 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?


    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
     
    White Wolf, Sep 11, 2003
    #2
    1. Advertising

  3. Andrew Ward

    Jim Fischer Guest

    Andrew Ward wrote:
    > Hi All,
    > Could someone please tell me why this code does not compile.


    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_link5809{at}now.here.com
     
    Jim Fischer, Sep 11, 2003
    #3
  4. Andrew Ward

    Andrew Ward Guest

    "White Wolf" <> wrote in message
    news:bjodhd$70o$...
    > Andrew Ward wrote:
    > > 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?

    >
    > 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
    >
    >


    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
     
    Andrew Ward, Sep 11, 2003
    #4
  5. Andrew Ward wrote:

    > "White Wolf" <> wrote in message
    > news:bjodhd$70o$...
    >
    >>Andrew Ward wrote:
    >>
    >>>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?

    >>
    >>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
    >>
    >>

    >
    >
    > 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?
    >


    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.
     
    Kevin Goodsell, Sep 11, 2003
    #5
  6. Andrew Ward

    Jim Fischer Guest

    Kevin Goodsell wrote:
    >> Maybe Jim Fischer's suggestion is correct?
    >>

    >
    > 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.


    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_link5809{at}now.here.com
     
    Jim Fischer, Sep 11, 2003
    #6
  7. Andrew Ward

    White Wolf Guest

    Andrew Ward wrote:
    [SNIP]
    > 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?


    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
     
    White Wolf, Sep 11, 2003
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Harrison
    Replies:
    4
    Views:
    481
    John Harrison
    Aug 7, 2003
  2. Bolin
    Replies:
    4
    Views:
    411
  3. Ravishankar S

    function prototype vs function declaration

    Ravishankar S, Dec 18, 2007, in forum: C Programming
    Replies:
    44
    Views:
    1,553
    Flash Gordon
    Dec 23, 2007
  4. June Lee
    Replies:
    2
    Views:
    809
    Jim Cobban
    Apr 13, 2008
  5. Hill Pang
    Replies:
    8
    Views:
    1,126
    Phil Carmody
    Sep 5, 2012
Loading...

Share This Page