By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,042 Members | 1,036 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,042 IT Pros & Developers. It's quick & easy.

std::auto_ptr / template question

P: n/a

Part of my confusion here is certainly my ignorance of templates and
std::auto_ptr. Two topics, I've perused but need to really _delve_
into. In any event, consider the 'test' source.

# include <iostream>
# include <memory>
class CallbackBase
{
public:
virtual void operator()() const { };
virtual ~CallbackBase() = 0;
};

CallbackBase::~CallbackBase() { }

template<typename T>
class Callback : public CallbackBase
{
public:
typedef void (T::*F)();

Callback( T& t, F f ) : t_(&t), f_(f) { }
void operator()() const { (t_->*f_)(); }

private:
T* t_;
F f_;
};

template<typename T>
Callback<T> make_callback( T& t, void (T::*f) () ) {
return Callback<T>( t, f );
}

template<class T>
std::auto_ptr<CallbackBase> new_callback( T& t, void(T::*f)() ) {
return std::auto_ptr<CallbackBase>( new Callback<T>(t,f) ); }

class XYZ {
std::auto_ptr<CallbackBase> my_cb;
static void cb_test()
{
// call the user function passed in to the
// constructor of the sndr & slComm.
//CallbackBase& cb = *static_cast<CallbackBase*>(&my_cb.get());
//cb();
}
public:
template<typename T>
XYZ( T& t,
void(T::*f)() )
: my_cb( new_callback(t,f) )
{}
};

class use {
XYZ *x;
public:
use()
{
x = new XYZ(this, use::test_funct); // DOESN'T WORK
}
void test_funct() {
std::cout << " test_func called " << std::endl;
}
~use () { delete x; }
};

int main()
{
//use u;
}

1 ////
I'm trying to create an instance of the class XYZ within 'use'
constructor but the .NET 2003 compiler complains, that the constructor
for XYZ does _not_ take 2 parameters.

'XYZ::XYZ' : function does not take 2 parameters

Make no sense.

2////
Within the cb_test member function whats the right approach to calling
the void function passed into XYZ?
The commented out portion. i.e.

//CallbackBase& cb = *static_cast<CallbackBase*>(&my_cb.get());
//cb();
doesn't work

Jul 23 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
> Part of my confusion here is certainly my ignorance of templates and
std::auto_ptr. Two topics, I've perused but need to really _delve_
It seems to be more with the basics than with std::auto_ptr and
templates.
into. In any event, consider the 'test' source. # include <iostream>
# include <memory>

class CallbackBase
{
public:
virtual void operator()() const { };
virtual ~CallbackBase() = 0;

};

CallbackBase::~CallbackBase() { }

template<typename T>
class Callback : public CallbackBase
{
public:
typedef void (T::*F)();

Callback( T& t, F f ) : t_(&t), f_(f) { }
void operator()() const { (t_->*f_)(); }

private:
T* t_;
F f_;

};

template<typename T>
Callback<T> make_callback( T& t, void (T::*f) () ) {
return Callback<T>( t, f );

}

template<class T>
std::auto_ptr<CallbackBase> new_callback( T& t, void(T::*f)() ) {
return std::auto_ptr<CallbackBase>( new Callback<T>(t,f) ); }

class XYZ {
std::auto_ptr<CallbackBase> my_cb;
static void cb_test()
{
// call the user function passed in to the
// constructor of the sndr & slComm.
//CallbackBase& cb = *static_cast<CallbackBase*>(&my_cb.get());
//cb();
}
public:
template<typename T>
XYZ( T& t,
void(T::*f)() )
: my_cb( new_callback(t,f) )
{}

};

class use {
XYZ *x;
public:
use()
{
x = new XYZ(this, use::test_funct); // DOESN'T WORK
Of course. this is a pointer, not a reference, and member functions do
not decay to their address like free functions do.

x = new XYZ(*this, &use::test_funct);
}
void test_funct() {
std::cout << " test_func called " << std::endl;
}
~use () { delete x; }

};

int main()
{
//use u;

}

1 ////
I'm trying to create an instance of the class XYZ within 'use'
constructor but the .NET 2003 compiler complains, that the constructor
for XYZ does _not_ take 2 parameters.

'XYZ::XYZ' : function does not take 2 parameters
If that's the actual message, it is poorly diagnosed. It should be
something like "no instance of constructor XYZ::XYZ matches the
argument list".
Make no sense.
You must learn (unfortunately) to interpret compiler errors.
2////
Within the cb_test member function whats the right approach to calling
the void function passed into XYZ?
The commented out portion. i.e.

//CallbackBase& cb = *static_cast<CallbackBase*>(&my_cb.get());
//cb(); doesn't work


Well cb_test() is static and 'my_cb' is not, so that's illegal. Either
make cb_test() non static of 'my_cb' static and it should work with

CallbackBase &cb = *my_cb;
cb();

or simply

(*my_cb)();

By the way, what do you gain by allocation callbacks on the heap?
Jonathan

Jul 23 '05 #2

P: n/a
On Tue, 12 Jul 2005 15:39:12 +0400, <ma******@pegasus.cc.ucf.edu> wrote:

[]
class XYZ {
std::auto_ptr<CallbackBase> my_cb;
static void cb_test()
{
// call the user function passed in to the
// constructor of the sndr & slComm.
//CallbackBase& cb = *static_cast<CallbackBase*>(&my_cb.get());
//cb();
You can invoke it simply:

(*my_cb)();
}
public:
template<typename T>
XYZ( T& t,
void(T::*f)() )
: my_cb( new_callback(t,f) )
{}
};

class use {
XYZ *x;
public:
use()
{
x = new XYZ(this, use::test_funct); // DOESN'T WORK


You must use an ampersand for taking a member function address and pass a
reference to *this, rather than this.

x = new XYZ(*this, &use::test_funct);

--
Maxim Yegorushkin
<fi****************@gmail.com>
Jul 23 '05 #3

P: n/a

<ma******@pegasus.cc.ucf.edu> wrote in message
news:11*********************@g14g2000cwa.googlegro ups.com...
Part of my confusion here is certainly my ignorance of templates and
std::auto_ptr. Two topics, I've perused but need to really _delve_
into. In any event, consider the 'test' source.
Actually, neither of the 2 errors you have reported is caused
by auto_ptr or templates -- although their presence makes it
difficult to find the problem (as your compiler may not
give very helpful error messages).
[not that it wouldn't be a good idea to study those 2 features]
# include <iostream>
# include <memory>
class CallbackBase
{
public:
virtual void operator()() const { };
virtual ~CallbackBase() = 0;
};

CallbackBase::~CallbackBase() { }

template<typename T>
class Callback : public CallbackBase
{
public:
typedef void (T::*F)();

Callback( T& t, F f ) : t_(&t), f_(f) { }
void operator()() const { (t_->*f_)(); }

private:
T* t_;
F f_;
};

template<typename T>
Callback<T> make_callback( T& t, void (T::*f) () ) {
return Callback<T>( t, f );
}

template<class T>
std::auto_ptr<CallbackBase> new_callback( T& t, void(T::*f)() ) {
return std::auto_ptr<CallbackBase>( new Callback<T>(t,f) ); }

class XYZ {
std::auto_ptr<CallbackBase> my_cb;
static void cb_test()
{
// call the user function passed in to the
// constructor of the sndr & slComm.
//CallbackBase& cb = *static_cast<CallbackBase*>(&my_cb.get());
//cb();
The proper syntax would be:
(*my_cb)(); // or (*my_cb.get())()
Which of course can be written in two steps:
CallbackBase& cb = *my_cb; // no cast required...
cb();

HOWEVER:
cb_test() being a *static* member function, it can only
access global variables or other static members of the class.
It cannot access a non-static member of cb_test().

So for the code to compile, my_cb() would have to be
a static data member of XYZ:
static std::auto_ptr<CallbackBase> my_cb;

You have to keep in mind that if you create multiple
instances of class XYZ, all these instances will share
the same "copy" of my_cb.
}
public:
template<typename T>
XYZ( T& t,
void(T::*f)() )
: my_cb( new_callback(t,f) )
{}
};

class use {
XYZ *x;
public:
use()
{
x = new XYZ(this, use::test_funct); // DOESN'T WORK
The first parameter needs to be an object reference ('this'
is a pointer), and you need a & to take the address of a
member function.
The corrected line becomes:
x = new XYZ(*this, &use::test_funct);
}
void test_funct() {
std::cout << " test_func called " << std::endl;
}
~use () { delete x; }
};

I hope this helps,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <> http://www.brainbench.com
Jul 23 '05 #4

P: n/a
"Jonathan Mcdougall" <jo***************@gmail.com> wrote in message
news:11*********************@z14g2000cwz.googlegro ups.com...
Part of my confusion here is certainly my ignorance of templates and
std::auto_ptr. Two topics, I've perused but need to really _delve_ .... class CallbackBase
{
public:
virtual void operator()() const { };
virtual ~CallbackBase() = 0;

};

CallbackBase::~CallbackBase() { }

template<typename T>
class Callback : public CallbackBase
{
public:
typedef void (T::*F)();

Callback( T& t, F f ) : t_(&t), f_(f) { }
void operator()() const { (t_->*f_)(); }

private:
T* t_;
F f_;

}; .... template<class T>
std::auto_ptr<CallbackBase> new_callback( T& t, void(T::*f)() ) {
return std::auto_ptr<CallbackBase>( new Callback<T>(t,f) ); }
.... By the way, what do you gain by allocation callbacks on the heap?


Subclasses of CallbackBase have to be allocated on the heap
to be used polymorphically at run-time: by calling the base
class, 'users' may call any type of object (via a Callback<T>
subclass).
So this is a correct approach.

This said: one could use a pointer to a (template-implemented)
function as an adaptor, rather than a class hierarchy.
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <> http://www.brainbench.com
Jul 23 '05 #5

P: n/a
| It seems to be more with the basics than with std::auto_ptr and
templates.
True and admittidely, I purchased a slew of highly recommended books
from accu but when it comes to templates and auto_ptr, I just 'scanned'
them with the intent to revisit later.

|x = new XYZ(*this, &use::test_funct);
Still doesn't work. Same error:
c:\sw_dev\C++\test\test.cpp(72) : error C2660: 'XYZ::XYZ' : function
does not take 2 parameters

Here's my confusion though: Can you have a template constructor in a
non-template class?

| By the way, what do you gain by allocation callbacks on the heap?
Sounds like the member function 'make_callback' is the right approach
as opposed to 'new_callback'

Jul 23 '05 #6

P: n/a
| Still doesn't work. Same error:

Oops!! Never mind. The error generated by the compiler is so
CRYPTIC. Anyways, the 'static' keyword on the member function
test_func was doing injustice.

Thanks ALL !!!!!

Jul 23 '05 #7

P: n/a
>>> class CallbackBase
{
public:
virtual void operator()() const { };
virtual ~CallbackBase() = 0;
};
By the way, what do you gain by allocation callbacks on the heap?
Subclasses of CallbackBase have to be allocated on the heap
to be used polymorphically at run-time: by calling the base
class, 'users' may call any type of object (via a Callback<T>
subclass).
So this is a correct approach.


Well I certainly missed the virtual functions in CallbackBase, but I
don't see how, with the current design, they are useful. If the OP
projects to have other types of callbacks (such as for free functions),
I stand corrected.

Jonathan

Jul 23 '05 #8

P: n/a
"Jonathan Mcdougall" <jo***************@gmail.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
class CallbackBase
{
public:
virtual void operator()() const { };
virtual ~CallbackBase() = 0;
}; By the way, what do you gain by allocation callbacks on the heap?

Subclasses of CallbackBase have to be allocated on the heap
to be used polymorphically at run-time: by calling the base
class, 'users' may call any type of object (via a Callback<T>
subclass).
So this is a correct approach.


Well I certainly missed the virtual functions in CallbackBase, but I
don't see how, with the current design, they are useful. If the OP
projects to have other types of callbacks (such as for free functions),
I stand corrected.


If not, the problem is not only the pointless heap allocation,
but also the irrelevant Callback class hierarchy.

We agree -Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Jul 23 '05 #9

P: n/a
| So for the code to compile, my_cb() would have to be a static data
member of XYZ:
| static std::auto_ptr<CallbackBase> my_cb;

Got it. So the templated constructor for XYZ becomes

template<typename T>
XYZ( T& t, void(T::*f)() )
// : my_cb( new_callback(t,f) ) // can't use initilization list on
static 'items'
{
my_cb = new_callback(t,f);
}

Make sense!! You guys are good. Thanks

Jul 23 '05 #10

P: n/a

| If the OP projects to have other types of callbacks (such as for free
functions),

Jonathan, that's correct. Thanks again

Jul 23 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.