Constructors taking single temporary objects mistaken for functionpointers?

Discussion in 'C++' started by jason.cipriani@gmail.com, Dec 25, 2008.

  1. Guest

    The following program fails to compile with what appears to be a
    really strange error:

    struct A {
    };

    struct B {
    B (const A&);
    void f();
    };

    int main () {
    B b(A()); // pass temporary A to constructor.
    b.f();
    }

    Comeau gives:

    "ComeauTest.c", line 12: error: expression must have class type
    b.f();

    MSVC gives:

    c:\temp\pqueue\pqueue.cpp(12) : error C2228: left of '.f' must have
    class/struct/union

    And "geordi", some weird C++ compiling IRC bot, gives:

    error: request for member 'f' in 'b', which is of non-class type 'B ()
    (A (*)())'

    What the heck is going on here? I am able to make it compile by
    putting the A() inside an extra set of parentheses:

    int main () {
    B b((A()));
    b.f();
    }

    But I'm not sure why it's mistaking what I'm trying to do for a
    function pointer declaration. I first ran into this error in the
    seemingly reasonable program:

    #include <queue>
    int main () {
    std::priority_queue<int> pq(less<int>());
    pq.push(0);
    }

    Where I was attempting to pass a predicate function to the
    constructor. Although the following fails with the same error:

    #include <queue>
    int main () {
    std::priority_queue<int> pq();
    pq.push(0);
    }

    In fact, any program of this form fails to compile:

    struct A { void f(); };
    int main () {
    A a();
    a.f();
    }

    And that completely boggles my mind for two reasons:

    1. While empty parens for default constructor are not the usual
    style, that seems like entirely reasonable code.
    2. I'm no master, but I am completely confused as to how I've never
    noticed this before, I feel like I've been programming long enough to
    have run into it at least once.

    Why are these programs not compiling? I mean, I understand that it
    thinks I'm declaring function pointers for some reason, but it doesn't
    make any sense to me why it would think that.

    Thanks,
    JC
    , Dec 25, 2008
    #1
    1. Advertising

  2. Rolf Magnus Guest

    Re: Constructors taking single temporary objects mistaken for function pointers?

    wrote:

    > The following program fails to compile with what appears to be a
    > really strange error:
    >
    > struct A {
    > };
    >
    > struct B {
    > B (const A&);
    > void f();
    > };
    >
    > int main () {
    > B b(A()); // pass temporary A to constructor.


    There is neither a temporary, nor a constructor involved here. The above
    declares a function named b, returning a B and taking a pointer to a
    function returning an A as parameter.

    > b.f();
    > }


    > What the heck is going on here? I am able to make it compile by
    > putting the A() inside an extra set of parentheses:
    >
    > int main () {
    > B b((A()));
    > b.f();
    > }
    >
    > But I'm not sure why it's mistaking what I'm trying to do for a
    > function pointer declaration.


    Because that's how C++ works. If it looks like a function declaration, it is
    a function declaration.

    > I first ran into this error in the
    > seemingly reasonable program:
    >
    > #include <queue>
    > int main () {
    > std::priority_queue<int> pq(less<int>());
    > pq.push(0);
    > }
    >
    > Where I was attempting to pass a predicate function to the
    > constructor. Although the following fails with the same error:
    >
    > #include <queue>
    > int main () {
    > std::priority_queue<int> pq();
    > pq.push(0);
    > }
    >
    > In fact, any program of this form fails to compile:
    >
    > struct A { void f(); };
    > int main () {
    > A a();
    > a.f();
    > }
    >
    > And that completely boggles my mind for two reasons:
    >
    > 1. While empty parens for default constructor are not the usual
    > style, that seems like entirely reasonable code.


    Well, how would you write a declaration for a function named a, returning an
    A? Would that not be:

    A a();

    ? And if it would, how can the compiler know that you want something else
    here?

    > Why are these programs not compiling? I mean, I understand that it
    > thinks I'm declaring function pointers for some reason, but it doesn't
    > make any sense to me why it would think that.


    The reason is that it looks like a function declaration.
    Rolf Magnus, Dec 25, 2008
    #2
    1. Advertising

  3. wrote, On 25.12.2008 9:44:
    > The following program fails to compile with what appears to be a
    > really strange error:
    >
    > struct A {
    > };
    >
    > struct B {
    > B (const A&);
    > void f();
    > };
    >
    > int main () {
    > B b(A()); // pass temporary A to constructor.
    > b.f();
    > }
    >
    > Comeau gives:
    >
    > "ComeauTest.c", line 12: error: expression must have class type
    > b.f();
    >
    > MSVC gives:
    >
    > c:\temp\pqueue\pqueue.cpp(12) : error C2228: left of '.f' must have
    > class/struct/union
    >
    > And "geordi", some weird C++ compiling IRC bot, gives:
    >
    > error: request for member 'f' in 'b', which is of non-class type 'B ()
    > (A (*)())'
    >
    > What the heck is going on here? I am able to make it compile by
    > putting the A() inside an extra set of parentheses:
    >
    > int main () {
    > B b((A()));
    > b.f();
    > }
    >
    > But I'm not sure why it's mistaking what I'm trying to do for a
    > function pointer declaration. I first ran into this error in the
    > seemingly reasonable program:
    >
    > #include <queue>
    > int main () {
    > std::priority_queue<int> pq(less<int>());
    > pq.push(0);
    > }
    >
    > Where I was attempting to pass a predicate function to the
    > constructor. Although the following fails with the same error:
    >
    > #include <queue>
    > int main () {
    > std::priority_queue<int> pq();
    > pq.push(0);
    > }
    >
    > In fact, any program of this form fails to compile:
    >
    > struct A { void f(); };
    > int main () {
    > A a();
    > a.f();
    > }
    >
    > And that completely boggles my mind for two reasons:
    >
    > 1. While empty parens for default constructor are not the usual
    > style, that seems like entirely reasonable code.
    > 2. I'm no master, but I am completely confused as to how I've never
    > noticed this before, I feel like I've been programming long enough to
    > have run into it at least once.
    >
    > Why are these programs not compiling? I mean, I understand that it
    > thinks I'm declaring function pointers for some reason, but it doesn't
    > make any sense to me why it would think that.

    Basically, anything that looks like a function declaration _is_ function
    declaration. Anything of the form <type> name (<type>); is function declaration.

    Let's say we modify your code like this:

    #include <iostream>

    // Your A and B classes.

    int main () {
    B b((A())); // pass temporary A to constructor.
    void foo (int ()); // the int() is actually int(*)()
    foo (0);
    b.f();
    }

    void foo (int(*)())
    {
    std::cout << "ahoy!" << std::endl;
    }

    The void foo (int ()); declaration does declare a function like your A b
    (A()); would. If you compile the modified test case it will print "ahoy!". If
    you remove the declaration inside main() then it will not compile at all.

    >
    > Thanks,
    > JC


    --
    VH
    Vaclav Haisman, Dec 25, 2008
    #3
  4. Guest

    Re: Constructors taking single temporary objects mistaken forfunction pointers?

    On Dec 25, 5:13 am, Rolf Magnus <> wrote:
    > wrote:
    > > The following program fails to compile with what appears to be a
    > > really strange error:

    >
    > > struct A {
    > > };

    >
    > > struct B {
    > >   B (const A&);
    > >   void f();
    > > };

    >
    > > int main () {
    > >   B b(A()); // pass temporary A to constructor.

    >
    > There is neither a temporary, nor a constructor involved here. The above
    > declares a function named b, returning a B and taking a pointer to a
    > function returning an A as parameter.
    >
    > >   b.f();
    > > }
    > > What the heck is going on here? I am able to make it compile by
    > > putting the A() inside an extra set of parentheses:

    >
    > > int main () {
    > >   B b((A()));
    > >   b.f();
    > > }

    >
    > > But I'm not sure why it's mistaking what I'm trying to do for a
    > > function pointer declaration.

    >
    > Because that's how C++ works. If it looks like a function declaration, it is
    > a function declaration.
    >
    >
    >
    > > I first ran into this error in the
    > > seemingly reasonable program:

    >
    > > #include <queue>
    > > int main () {
    > > std::priority_queue<int> pq(less<int>());
    > > pq.push(0);
    > > }

    >
    > > Where I was attempting to pass a predicate function to the
    > > constructor. Although the following fails with the same error:

    >
    > > #include <queue>
    > > int main () {
    > > std::priority_queue<int> pq();
    > > pq.push(0);
    > > }

    >
    > > In fact, any program of this form fails to compile:

    >
    > > struct A { void f(); };
    > > int main () {
    > >   A a();
    > >   a.f();
    > > }

    >
    > > And that completely boggles my mind for two reasons:

    >
    > >   1. While empty parens for default constructor are not the usual
    > > style, that seems like entirely reasonable code.

    >
    > Well, how would you write a declaration for a function named a, returning an
    > A? Would that not be:
    >
    > A a();
    >
    > ? And if it would, how can the compiler know that you want something else
    > here?
    >
    > > Why are these programs not compiling? I mean, I understand that it
    > > thinks I'm declaring function pointers for some reason, but it doesn't
    > > make any sense to me why it would think that.

    >
    > The reason is that it looks like a function declaration.



    Thanks for clearing it up; I guess it caught me by surprise. It seems
    a little ... almost sloppy ... of the grammar to make you add an extra
    set of parentheses around a function parameter like that. I guess
    anything of the form:

    Type name(Type(), Type(), Type(), ...)

    Would look like a function pointer. For example, I do this:

    struct B {
    B (int, int, int) { }
    void f();
    };

    int main () {
    B b(int(), int(), int());
    b.f();
    }

    And I get the error, yet putting an extra set of parentheses around
    any single one of those int()s (doesn't matter which) makes everything
    OK again, e.g.:

    B b(int(), (int()), int());
    b.f();

    It seems sloppy in the same way the nested template >> thing is
    sloppy.

    Of course, now that I know what's going on, it's easy to not make the
    mistake again. Also, I guess I don't really have any idea of how to
    make it less... strange. Still, it did catch me off guard and made me
    raise an eyebrow a little.

    Thanks,
    Jason
    , Dec 27, 2008
    #4
  5. Guest

    Re: Constructors taking single temporary objects mistaken forfunction pointers?

    On Dec 25, 5:21 pm, Vaclav Haisman <> wrote:
    > wrote, On 25.12.2008 9:44:
    >
    > > The following program fails to compile with what appears to be a
    > > really strange error:

    >
    > > struct A {
    > > };

    >
    > > struct B {
    > >   B (const A&);
    > >   void f();
    > > };

    >
    > > int main () {
    > >   B b(A()); // pass temporary A to constructor.
    > >   b.f();
    > > }

    >
    > > Comeau gives:

    >
    > > "ComeauTest.c", line 12: error: expression must have class type
    > >     b.f();

    >
    > > MSVC gives:

    >
    > > c:\temp\pqueue\pqueue.cpp(12) : error C2228: left of '.f' must have
    > > class/struct/union

    >
    > > And "geordi", some weird C++ compiling IRC bot, gives:

    >
    > > error: request for member 'f' in 'b', which is of non-class type 'B ()
    > > (A (*)())'

    >
    > > What the heck is going on here? I am able to make it compile by
    > > putting the A() inside an extra set of parentheses:

    >
    > > int main () {
    > >   B b((A()));
    > >   b.f();
    > > }

    >
    > > But I'm not sure why it's mistaking what I'm trying to do for a
    > > function pointer declaration. I first ran into this error in the
    > > seemingly reasonable program:

    >
    > > #include <queue>
    > > int main () {
    > >    std::priority_queue<int> pq(less<int>());
    > >    pq.push(0);
    > > }

    >
    > > Where I was attempting to pass a predicate function to the
    > > constructor. Although the following fails with the same error:

    >
    > > #include <queue>
    > > int main () {
    > >    std::priority_queue<int> pq();
    > >    pq.push(0);
    > > }

    >
    > > In fact, any program of this form fails to compile:

    >
    > > struct A { void f(); };
    > > int main () {
    > >   A a();
    > >   a.f();
    > > }

    >
    > > And that completely boggles my mind for two reasons:

    >
    > >   1. While empty parens for default constructor are not the usual
    > > style, that seems like entirely reasonable code.
    > >   2. I'm no master, but I am completely confused as to how I've never
    > > noticed this before, I feel like I've been programming long enough to
    > > have run into it at least once.

    >
    > > Why are these programs not compiling? I mean, I understand that it
    > > thinks I'm declaring function pointers for some reason, but it doesn't
    > > make any sense to me why it would think that.

    >
    > Basically, anything that looks like a function declaration _is_ function
    > declaration. Anything of the form <type> name (<type>); is function declaration.
    >
    > Let's say we modify your code like this:
    >
    > #include <iostream>
    >
    > // Your A and B classes.
    >
    > int main () {
    >   B b((A())); // pass temporary A to constructor.
    >   void foo (int ()); // the int() is actually int(*)()
    >   foo (0);
    >   b.f();
    >
    > }
    >
    > void foo (int(*)())
    > {
    >   std::cout << "ahoy!" << std::endl;
    >
    > }
    >
    > The void foo (int ()); declaration does declare a function like your A b
    > (A()); would. If you compile the modified test case it will print "ahoy!".. If
    >  you remove the declaration inside main() then it will not compile at all.


    Thanks, that was a good explanation.

    Jason
    , Dec 27, 2008
    #5
    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. Mohun Biswas

    fixing a mistaken toString() method

    Mohun Biswas, Aug 2, 2003, in forum: Java
    Replies:
    1
    Views:
    352
  2. Henning Hasemann
    Replies:
    17
    Views:
    1,141
    mangesh
    Jun 30, 2006
  3. Replies:
    7
    Views:
    3,210
    James Kanze
    Feb 12, 2008
  4. David Given
    Replies:
    4
    Views:
    346
    David Given
    Jun 14, 2008
  5. A.Gallus
    Replies:
    5
    Views:
    286
    A.Gallus
    Oct 7, 2008
Loading...

Share This Page