From: random.sampling@gmail.com on
Hello,
when I try to use atexit() from a C++ class, my compiler is giving me
an error.

error C2664: 'atexit' : cannot convert parameter 1 from 'void (void)'
to 'void (__cdecl *)(void)'

Is it possible to use atexit() with a C++ class member or only with
global functions?

Thank you in advance,
Marco

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

#include <cstdlib>

namespace test
{
class foo
{
public:
foo(){};
~foo(){};
void Killfoo()
{foo->~foo();}
void RegisterForDestruction()
{atexit(killFoo);}
};
}

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


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Joe Gottman on

<random.sampling(a)gmail.com> wrote in message
news:1139116406.431988.317710(a)z14g2000cwz.googlegroups.com...
> Hello,
> when I try to use atexit() from a C++ class, my compiler is giving me
> an error.
>
> error C2664: 'atexit' : cannot convert parameter 1 from 'void (void)'
> to 'void (__cdecl *)(void)'
>
> Is it possible to use atexit() with a C++ class member or only with
> global functions?
>
> Thank you in advance,
> Marco
>
> /////////////////
>
> #include <cstdlib>
>
> namespace test
> {
> class foo
> {
> public:
> foo(){};
> ~foo(){};
> void Killfoo()
> {foo->~foo();}
> void RegisterForDestruction()
> {atexit(killFoo);}
> };
> }

It's possible. I do this all the time, mostly for destroying Singletons.
The problem is that the function you pass to atexit has to be a static
member function. Non-static member functions have a this parameter of type
foo *, and the atexit function has no way of obtaining a this pointer to use
with KillFoo. So to do what you want, you will need to keep a static
container of pointers to objects you want to destroy, and use
RegisterForDestruction to add new pointers to this container. Then have a
private static destroyAll() function that actually calls Killfoo() on all
the pointers in the container, and register destroyAll() with atexit.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Francis Glassborow on
In article <1139116406.431988.317710(a)z14g2000cwz.googlegroups.com>,
"random.sampling(a)gmail.com" <random.sampling(a)gmail.com> writes
>Hello,
>when I try to use atexit() from a C++ class, my compiler is giving me
>an error.
>
>error C2664: 'atexit' : cannot convert parameter 1 from 'void (void)'
>to 'void (__cdecl *)(void)'

That may not be the clearest error message but it is correct in what it
tries to say. There is no conversion from a member function to a free
function.
>
>Is it possible to use atexit() with a C++ class member or only with
>global functions?
Even if there were not the conversion problem there would still be a
major problem. atexit functions are called without arguments, a member
function always has an implicit parameter, that of the instance on whose
behalf it is being called. How could a member function be called in the
context of a call of exit()? Nor is there any way to wrap the member
function into a free function with no parameters.

Just think about it and you will realise that it is not possible (the
same is not true for static member functions.



--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Valentin Samko on
random.sampling(a)gmail.com wrote:
> Hello,
> when I try to use atexit() from a C++ class, my compiler is giving me
> an error.
>
> error C2664: 'atexit' : cannot convert parameter 1 from 'void (void)'
> to 'void (__cdecl *)(void)'
>
> Is it possible to use atexit() with a C++ class member or only with
> global functions?

No, you can not use atexit with a member function, it must be a pointer to a non member
function with a void(*)() signature. You can always work around that by setting one atexit
handler which will execute all your C++ handlers. For example,

typedef std::list<boost::function<void()> > actions;
actions execute_at_exit;
void at_exit_helper() {
for (actions::const_iterator action = execute_at_exit.begin(); action !=
execute_at_exit.end(); ++action)
(*action)();
}

and then you can do
struct X { void foo(); };
X* x = new X();
actions.push_back(boost::bind(&X::foo, x));

--

Valentin Samko - http://www.valentinsamko.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Thomas Maeder on
"random.sampling(a)gmail.com" <random.sampling(a)gmail.com> writes:

[rearranged by tm]

>
> Thank you in advance,
> Marco
>
> /////////////////
>
> #include <cstdlib>
>
> namespace test
> {
> class foo
> {
> public:
> foo(){};
> ~foo(){};
> void Killfoo()
> {foo->~foo();}
> void RegisterForDestruction()
> {atexit(killFoo);}
> };
> }
>
> when I try to use atexit() from a C++ class, my compiler is giving
> me an error.
>
> error C2664: 'atexit' : cannot convert parameter 1 from 'void (void)'
> to 'void (__cdecl *)(void)'

The immediate reason for this strange message seems to be that the
compiler can't figure out what killFoo means. The member function is
called Killfoo, with a capital 'K' and non-capital 'f'.


> Is it possible to use atexit() with a C++ class member or only with
> global functions?

No.

atexit() requires its argument to be of type void (*)(), i.e. 'pointer
to function taking no argument and with return type void'. This
includes global functions, such as

void f()
{
}

, but also functions that belong to a namespace, such as

namespace foo
{
void g()
{
}
}


It is not possible to use a non-static member function,
though. E.g. the type of &::test::foo::Killfoo is void
(::test::foo::*)(), which isn't convertible to void (*)().

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]