[C++] " request for member function ... non-class type"

Started by
6 comments, last by Zahlman 14 years, 12 months ago
I get the following error:
E:\C\main.cpp:173: error: request for member `retain' in `foo',
which is of non-class type `Pointer<Foo> ()(Foo
(*)())'
E:\C\main.cpp:174: error: request for member `release' in `foo',
which is of non-class type `Pointer<Foo> ()(Foo
(*)())'
Which is rather strange if you consider the following code:
    template <class T>
    class Pointer
    {
    public:
        Pointer(T instance = T())
        {
            _pointer = new T(instance);
        }

        Pointer(T *instance)
        {
            _pointer = new T(*instance);
        }

        ~Pointer()
        {
            release();
        }

        // shouldn't use this one really
        T *pointer()
        {
            return _pointer;
        }

        // get the pointer, increase the count
        T *retain()
        {
            if (_pointer)
            {
                _pointer->references.gain();
            }
            return _pointer;
        }

        // decrease the count
        void release()
        {
            if (_pointer && !_pointer->references.lose())
            {
                delete _pointer;
                _pointer = NULL;
            }
        }

    private:
        T *_pointer;
    };

    ////////////////////////////////////////////////////////////////

    class Foo
    {
        // irrelevant
    };

int main()
{
    Pointer<Foo> foo(Foo()); // creates a new instance of Foo

    foo.retain(); // increases counter
    foo.release(); // decreases counter

    // pointers life time ends -> counter decreased -> Foo is deleted
}
Sure, it works if I do 'Pointer<Foo> foo;' but what is above should do exactly the same, that is, constructing a default Foo object. This is a test code, and the Foo's constructor would in almost all case accept parameters. Preferably I'd like this on one line. The following 2 example _DO_ work:
int main()
{
    Pointer<Foo> foo1;

    Foo tmp(/* parameters*/);
    Pointer<Foo> foo2(tmp);
}
Why does it give this weird error? It looks like it takes it as a function pointer...? PS: I can't (de)allocate (new / delete) in the main() function since the library could be compiled as a DLL, meaning I have to allocate on the lib and deallocate on the lib (or on the executable of course, but I choose the former). Thanks!
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
Advertisement
Im guessing you're a victim of "C++'s most vexing parse". Google for it and you will find better explanations than I can give you. Here is one link:
http://staff.it.uts.edu.au/~ypisan/programming/stl50.html

You can also look it up in one of Scott Meyer's books if you own a copy.
Changing that line to this should work:
Pointer<Foo> foo((Foo()));

Basically the compiler decides you were declaring a function instead of a variable. That line can be interpreted as either one. When in doubt the compiler favours functions in this case.
Thanks Icon, that was indeed the problem :-)
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
Alternatively, you can write
Pointer<Foo> foo = Foo();

which will call the (same) copy ctor.
This only works if the constructor is implicit though. There should be no problem for it to be explicit though, since it doesn't seem to do any dangerous thing such as ownership transfer.

However, your type obviously lacks a copy constructor and an assignment operator.
Quote:Original post by phresnel
Alternatively, you can write
*** Source Snippet Removed ***
which will call the (same) copy ctor.


Ah yes, you surprised me with that but it's indeed true. On initialisation operator= can be interpreted as if a constructor was called.

Quote:Original post by loufoque
This only works if the constructor is implicit though. There should be no problem for it to be explicit though, since it doesn't seem to do any dangerous thing such as ownership transfer.

However, your type obviously lacks a copy constructor and an assignment operator.


Good that you mention it, almost forgotten ;).

[Edited by - Decrius on April 20, 2009 11:37:49 AM]
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
Quote:Original post by Decrius
Ah yes, you surprised me with that but it's indeed true. On initialisation operator= can be interpreted as if a constructor was called.


It's not operator=, and it's not "can be interpreted". The initialization syntax with '=' calls the copy constructor, not operator=. Why? Because it's an initialization. You can't assign to something that hasn't been initialized yet, because an uninitialized thing (except for primtives) effectively doesn't exist yet.

You could also avoid the "vexing parse" by using a named temporary for the Foo object: Foo f; Pointer<Foo> foo(f);

This topic is closed to new replies.

Advertisement