templates and friends

  • Thread starter Kevin Christopher
  • Start date
K

Kevin Christopher

I've got a pile of code that won't compile for me, and can't figure out
why. I'm either making a template / friend / operator overloading
mistake (most likely - & why I'm asking here), or I'm using something
not supported by g++ 2.96 (less likely).

The big picture: I'm writing a wrapper class template that is supposed
to wrap around a primitive data type so that I can send myself
notifications whenever some code changes that data type (i.e. read from
or write to). My idea was a wrapper that overloads the operator=()
function. Works great, except for assigning with operator=(int,
wrapper) which doesn't compile. Demonstration code attached (somewhat
long, but all the relevant functions are there). Demonstration code
runs as is right now... there are three commented-out sections dealing
with the one friend function that I need to get compiling.

Can anyone tell me what I'm doing wrong? The g++ error message is:
operator=(base_t&, const notify_wrapper<base_t>)&) must be a
nonstatic member function
and I don't feel that it has to be - this is an external helper function
for when I want to do: (base_t) = wrapper<base_t>. And since base_t is
a primitive type, I can't add this as a member function.

(code follows as attachment)

-Kevin


#include <iostream>

class wrapper_listener
{
public:
virtual void written_to(void) {cout << "written" << endl;}
virtual void read_from(void) {cout << "read" << endl;}
};

template <typename base_t>
class notify_wrapper
{
public:
notify_wrapper() {}
~notify_wrapper() {}

public:
operator base_t ();

notify_wrapper<base_t>& operator=
(const notify_wrapper<base_t>& rhs);

notify_wrapper<base_t>& operator=
(const base_t& rhs);

/*
friend
void operator=<base_t>
(base_t& lhs, const notify_wrapper<base_t>& rhs);
*/

private:
base_t base;

public:
static wrapper_listener* listener;
};

/*
template <typename base_t>
void operator=
(base_t& lhs, const notify_wrapper<base_t>& rhs);
*/

template <typename base_t>
notify_wrapper<base_t>::eek:perator base_t
()
{
return this->base;
}

template <typename base_t>
notify_wrapper<base_t>&
notify_wrapper<base_t>::eek:perator=
(const notify_wrapper<base_t>& rhs)
{
base = (base_t) rhs.base;
if(rhs.listener) rhs.listener->read_from();
if(listener) listener->written_to();
}

template <typename base_t>
notify_wrapper<base_t>&
notify_wrapper<base_t>::eek:perator=
(const base_t& rhs)
{
base = rhs;
if(listener) listener->written_to();
return *this;
}
/*
template <typename base_t>
void //disallow future assignments!
::eek:perator=
(base_t& lhs, const notify_wrapper<base_t>& rhs)
{
lhs = (base_t) rhs.base;
if(listener) listener->read_from();
}
*/

wrapper_listener* notify_wrapper<int>::listener;

int main()
{
int i;
wrapper_listener wrapper;
notify_wrapper<int> tester;
notify_wrapper<int>::listener = &wrapper;
tester = 5;
i = tester;

return 0;
}
 
K

Kevin Christopher

Victor said:
Please do not post attachments in this newsgroup. If you need
to post code, copy and paste it into the message. However,
before you do that, please, read the FAQ 5.8.
Ironically enough, I managed to read the FAQ and distill out a sample
file without seeing the no-attachments part. Foolish of me.

Alas, here is the file, copy-and-pasted. I have beeen attempting to
compile it with g++ 2.96, simply with "g++ test.cc"

-Kevin
=================================================
#include <iostream>

class wrapper_listener
{
public:
virtual void written_to(void) {cout << "written" << endl;}
virtual void read_from(void) {cout << "read" << endl;}
};

template <typename base_t>
class notify_wrapper
{
public:
notify_wrapper() {}
~notify_wrapper() {}

public:
operator base_t ();

notify_wrapper<base_t>& operator=
(const notify_wrapper<base_t>& rhs);

notify_wrapper<base_t>& operator=
(const base_t& rhs);

/*
friend
void operator=<base_t>
(base_t& lhs, const notify_wrapper<base_t>& rhs);
*/

private:
base_t base;

public:
static wrapper_listener* listener;
};

/*
template <typename base_t>
void operator=
(base_t& lhs, const notify_wrapper<base_t>& rhs);
*/

template <typename base_t>
notify_wrapper<base_t>::eek:perator base_t
()
{
return this->base;
}

template <typename base_t>
notify_wrapper<base_t>&
notify_wrapper<base_t>::eek:perator=
(const notify_wrapper<base_t>& rhs)
{
base = (base_t) rhs.base;
if(rhs.listener) rhs.listener->read_from();
if(listener) listener->written_to();
}

template <typename base_t>
notify_wrapper<base_t>&
notify_wrapper<base_t>::eek:perator=
(const base_t& rhs)
{
base = rhs;
if(listener) listener->written_to();
return *this;
}
/*
template <typename base_t>
void //disallow future assignments!
::eek:perator=
(base_t& lhs, const notify_wrapper<base_t>& rhs)
{
lhs = (base_t) rhs.base;
if(listener) listener->read_from();
}
*/

wrapper_listener* notify_wrapper<int>::listener;

int main()
{
int i;
wrapper_listener wrapper;
notify_wrapper<int> tester;
notify_wrapper<int>::listener = &wrapper;
tester = 5;
i = tester;

return 0;
}
 
V

Victor Bazarov

Kevin Christopher said:
Ironically enough, I managed to read the FAQ and distill out a sample
file without seeing the no-attachments part. Foolish of me.

Alas, here is the file, copy-and-pasted. I have beeen attempting to
compile it with g++ 2.96, simply with "g++ test.cc"

(a) Having read the FAQ you still managed to follow the first
6 key guidelines but for some reason decided to ignore #7,
which IMHO is the most important. If you receive compiler
diagnostic, what is it? I don't have your compiler, nor do
I have your OS or anything else the compilation may depend
on. So, I cannot answer your inquiry. Neither can many of
other regulars here. Well, of course, I exaggerate a bit,
but still...

(b) Why are you using such an ancient compiler? Is there any
legitimate reason for you not to upgrade to something at
least a bit more Standard-compliant?

(c) In your code, add "using namespace std;" after the first line
(it may not help with g++ v2.96, but it will make your code
closer to legal C++).

(d) Add
template<class T> wrapper_listener* notify_wrapper<T>::listener;
before line 84.

(e) Line 85 (former 84) should look like this:
template wrapper_listener* notify_wrapper<int>::listener;

That should do it.

Victor
 
T

tom_usenet

/*
friend
void operator=<base_t>
(base_t& lhs, const notify_wrapper<base_t>& rhs);
*/

operator= has to be a member function according to the C++ standard.
You need:

friend base_t& base_t::eek:perator=(const notify_wrapper<base_t>& rhs);

Obviously, this won't work for built in types - you can't override the
meaning of assignment for built ins, which is a reasonable
restriction. You'll have to rethink your design.

Tom
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top