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

Assigment operator and container of base type

P: n/a

Below is an example of the problem I am having. I don't understand how
I can get the compiler to see deriv &operator=(const T &rhs).

I am sure this is a common problem - any suggestions?
#include <iostream>
#include <vector>

struct base
{
virtual ~base()=0 {};
};

template<class T>
struct deriv : public base
{
deriv(): data_(0) {};
deriv(const T &data): data_(data) {};
deriv &operator=(const T &rhs) { data_=rhs; return (*this); }
deriv &operator=(const deriv &rhs)
{ data_=rhs.data_; return (*this); }
T data_;
};

struct container
{
base &operator[](int i) { return *(data_[i]); };
std::vector<base *data_;
};

void fill_cont(container &data);

int main(int argc, char *argv[])
{
container data;
fill_cont(data);

std::cout << "data[0]=" << typeid(data[0]).name() << std::endl;
// output: data[0]=struct deriv<int>
data[0]=12445;

std::cout << "data[1]=" << typeid(data[1]).name() << std::endl;
// output: data[1]=struct deriv<double>
data[1]=4.5667;

std::cout << "data[2]=" << typeid(data[2]).name() << std::endl;
// output: data[2]=struct deriv<char *>
data[2]="test";

return 0;
}

void fill_cont(container &data)
{
data.data_.push_back(new deriv<int>());
data.data_.push_back(new deriv<double>());
data.data_.push_back(new deriv<char *>());
}

--

Adrian

Think you know a language? Post to comp.lang... and find out!
Dec 4 '06 #1
Share this Question
Share on Google+
10 Replies


P: n/a

Adrian napsal:
Below is an example of the problem I am having. I don't understand how
I can get the compiler to see deriv &operator=(const T &rhs).

I am sure this is a common problem - any suggestions?
#include <iostream>
#include <vector>

struct base
{
virtual ~base()=0 {};
};

template<class T>
struct deriv : public base
{
deriv(): data_(0) {};
deriv(const T &data): data_(data) {};
deriv &operator=(const T &rhs) { data_=rhs; return (*this); }
deriv &operator=(const deriv &rhs)
{ data_=rhs.data_; return (*this); }
T data_;
};

struct container
{
base &operator[](int i) { return *(data_[i]); };
std::vector<base *data_;
};

void fill_cont(container &data);

int main(int argc, char *argv[])
{
container data;
fill_cont(data);

std::cout << "data[0]=" << typeid(data[0]).name() << std::endl;
// output: data[0]=struct deriv<int>
data[0]=12445;

std::cout << "data[1]=" << typeid(data[1]).name() << std::endl;
// output: data[1]=struct deriv<double>
data[1]=4.5667;

std::cout << "data[2]=" << typeid(data[2]).name() << std::endl;
// output: data[2]=struct deriv<char *>
data[2]="test";

return 0;
}

void fill_cont(container &data)
{
data.data_.push_back(new deriv<int>());
data.data_.push_back(new deriv<double>());
data.data_.push_back(new deriv<char *>());
}

The code is quite long, but for me is strange for example pure virtual
destructor in base class.

Dec 4 '06 #2

P: n/a

Adrian napsal:
Below is an example of the problem I am having. I don't understand how
I can get the compiler to see deriv &operator=(const T &rhs).

I am sure this is a common problem - any suggestions?
#include <iostream>
#include <vector>

struct base
{
virtual ~base()=0 {};
};

template<class T>
struct deriv : public base
{
deriv(): data_(0) {};
deriv(const T &data): data_(data) {};
deriv &operator=(const T &rhs) { data_=rhs; return (*this); }
deriv &operator=(const deriv &rhs)
{ data_=rhs.data_; return (*this); }
T data_;
};

struct container
{
base &operator[](int i) { return *(data_[i]); };
std::vector<base *data_;
};

void fill_cont(container &data);

int main(int argc, char *argv[])
{
container data;
fill_cont(data);

std::cout << "data[0]=" << typeid(data[0]).name() << std::endl;
// output: data[0]=struct deriv<int>
data[0]=12445;

std::cout << "data[1]=" << typeid(data[1]).name() << std::endl;
// output: data[1]=struct deriv<double>
data[1]=4.5667;

std::cout << "data[2]=" << typeid(data[2]).name() << std::endl;
// output: data[2]=struct deriv<char *>
data[2]="test";

return 0;
}

void fill_cont(container &data)
{
data.data_.push_back(new deriv<int>());
data.data_.push_back(new deriv<double>());
data.data_.push_back(new deriv<char *>());
}

--

Adrian

Think you know a language? Post to comp.lang... and find out!
In container::operator[] you are returning reference to base. But there
is no assignment operator in class 'base', so compiler cannot see it.

Dec 4 '06 #3

P: n/a
Adrian wrote:
>
Below is an example of the problem I am having. I don't understand how
I can get the compiler to see deriv &operator=(const T &rhs).
The problem is that this function doesn't exist in base, which is the static
type. The compiler will only search the object's static type.
>
I am sure this is a common problem - any suggestions?
Surely. You can cast to whatever type you really have:

dynamic_cast<deriv<int>&>(data[0]) = 12445;

Another "solution" follows.
#include <iostream>
#include <vector>

struct base
{
template <class Tbase& operator=(const T&);
virtual ~base()=0 {};
of course this don't work, but your compiler will tell you that.
};

template<class T>
struct deriv : public base
{
deriv(): data_(0) {};
deriv(const T &data): data_(data) {};
deriv &operator=(const T &rhs) { data_=rhs; return (*this); }
deriv &operator=(const deriv &rhs)
{ data_=rhs.data_; return (*this); }
T data_;
};
template <class T>
base& base::operator=(const T& rhs)
{
return dynamic_cast<deriv<T>&>(*this) = rhs;
}
>
struct container
{
base &operator[](int i) { return *(data_[i]); };
std::vector<base *data_;
};

void fill_cont(container &data);

int main(int argc, char *argv[])
{
container data;
fill_cont(data);

std::cout << "data[0]=" << typeid(data[0]).name() << std::endl;
// output: data[0]=struct deriv<int>
data[0]=12445;

std::cout << "data[1]=" << typeid(data[1]).name() << std::endl;
// output: data[1]=struct deriv<double>
data[1]=4.5667;

std::cout << "data[2]=" << typeid(data[2]).name() << std::endl;
// output: data[2]=struct deriv<char *>
data[2]="test";
Of course "test" has type const char[5], not char*, so this will not work.
>
return 0;
}

void fill_cont(container &data)
{
data.data_.push_back(new deriv<int>());
data.data_.push_back(new deriv<double>());
data.data_.push_back(new deriv<char *>());
}
--
Robert Bauck Hamar
Der er to regler for suksess:
1. Fortell aldri alt du vet.
– Roger H. Lincoln
Dec 4 '06 #4

P: n/a
On 2006-12-04 21:07, Adrian wrote:
Below is an example of the problem I am having. I don't understand how
I can get the compiler to see deriv &operator=(const T &rhs).

I am sure this is a common problem - any suggestions?
#include <iostream>
#include <vector>

struct base
{
virtual ~base()=0 {};
};

template<class T>
struct deriv : public base
{
deriv(): data_(0) {};
deriv(const T &data): data_(data) {};
deriv &operator=(const T &rhs) { data_=rhs; return (*this); }
deriv &operator=(const deriv &rhs)
{ data_=rhs.data_; return (*this); }
T data_;
};

struct container
{
base &operator[](int i) { return *(data_[i]); };
std::vector<base *data_;
};

void fill_cont(container &data);

int main(int argc, char *argv[])
{
container data;
fill_cont(data);

std::cout << "data[0]=" << typeid(data[0]).name() << std::endl;
// output: data[0]=struct deriv<int>
data[0]=12445;

std::cout << "data[1]=" << typeid(data[1]).name() << std::endl;
// output: data[1]=struct deriv<double>
data[1]=4.5667;

std::cout << "data[2]=" << typeid(data[2]).name() << std::endl;
// output: data[2]=struct deriv<char *>
data[2]="test";

return 0;
}

void fill_cont(container &data)
{
data.data_.push_back(new deriv<int>());
data.data_.push_back(new deriv<double>());
data.data_.push_back(new deriv<char *>());
}
I'm quite sure you can't do that. Besides from what Ondra Holub has said
what you are trying to do is to create a heterogeneous container, which
I'm quite sure you can't do. At least not like that, you might succeed
if you first find out what kind of deriv it is and cast it to that type.
But then there would not be much of a point, would it?

--
Erik Wikström
Dec 4 '06 #5

P: n/a
Ondra Holub wrote:
In container::operator[] you are returning reference to base. But there
is no assignment operator in class 'base', so compiler cannot see it.
Should be. The compiler should generate one by default.
--

Adrian

Think you know a language? Post to comp.lang... and find out!
Dec 4 '06 #6

P: n/a
Ondra Holub wrote:
The code is quite long, but for me is strange for example pure virtual
destructor in base class.
This is a useful trick for insuring that the class is abstract.

--

Adrian

Think you know a language? Post to comp.lang... and find out!
Dec 4 '06 #7

P: n/a
Robert Bauck Hamar wrote:
Adrian wrote:
The problem is that this function doesn't exist in base, which is
the static
type. The compiler will only search the object's static type.
>I am sure this is a common problem - any suggestions?

Surely. You can cast to whatever type you really have:

dynamic_cast<deriv<int>&>(data[0]) = 12445;

Another "solution" follows.
>#include <iostream>
#include <vector>

struct base
{

template <class Tbase& operator=(const T&);
> virtual ~base()=0 {};

of course this don't work, but your compiler will tell you that.
What wont work. Nothing wrong with a virtual destructor?

template <class T>
base& base::operator=(const T& rhs)
{
return dynamic_cast<deriv<T>&>(*this) = rhs;
}
Perfect. I didnt try that. I assumed the compiler would never be able
to deduce T.

Thanks for that.
>
Of course "test" has type const char[5], not char*, so this will not work.
Was just throwing things into the example :-)

--

Adrian

Think you know a language? Post to comp.lang... and find out!
Dec 4 '06 #8

P: n/a
Adrian wrote:
Robert Bauck Hamar wrote:
>Adrian wrote:
The problem is that this function doesn't exist in base, which is
the static
>type. The compiler will only search the object's static type.
>>I am sure this is a common problem - any suggestions?

Surely. You can cast to whatever type you really have:

dynamic_cast<deriv<int>&>(data[0]) = 12445;

Another "solution" follows.
>>#include <iostream>
#include <vector>

struct base
{

template <class Tbase& operator=(const T&);
>> virtual ~base()=0 {};

of course this don't work, but your compiler will tell you that.
What wont work. Nothing wrong with a virtual destructor?
The dtor _should_, of course, be virtual. But the above line is a syntax
error. You _can_ do:

class foo {
virtual ~foo() = 0;
};

foo::~foo() {}

but not

class foo {
virtual ~foo() = 0 {}
};

--
Robert Bauck Hamar
Der er to regler for suksess:
1. Fortell aldri alt du vet.
- Roger H. Lincoln
Dec 4 '06 #9

P: n/a
Robert Bauck Hamar wrote:
The dtor _should_, of course, be virtual. But the above line is a syntax
error. You _can_ do:

class foo {
virtual ~foo() = 0;
};

foo::~foo() {}

but not

class foo {
virtual ~foo() = 0 {}
};
Gotya. Actually the compiler allows it. I hate it when they dont
follow standards, makes porting a nightmare.

Just found it in the standard. 10.4.2. Makes sense

--

Adrian

Think you know a language? Post to comp.lang... and find out!
Dec 4 '06 #10

P: n/a
Adrian wrote:
Ondra Holub wrote:
>In container::operator[] you are returning reference to base. But there
is no assignment operator in class 'base', so compiler cannot see it.

Should be. The compiler should generate one by default.
Surely. base& base::operator=(const base&) is declared by default. Remarks:

1. It does not match the signature of deriv<T>& deriv<T>::operator=(const
T&)
2. It is not virtual.

1 Means that when the comiler searches base (static type of lhs in
assignment) for operator=, it cannot see any operator= taking a T, even
though the dynamic type of lhs has one.

2 Means that even if the signatures had matched, the compiler would
statically link to base::operator=. Example of latter:

#include <iostream>

using namespace std;

struct foo {
virtual foo& operator =(const foo&) {
cout << "foo\n";
return *this;
}
};

struct bar : foo {
bar& operator=(const foo&) {
cout << "bar\n";
return *this;
}
};

int main() {
foo f;
bar b;

foo & fb = b;

f = f;
b = b;
fb = b;
}

Delete the virtual kw in foo, and see how output changes.

--
Robert Bauck Hamar
Der er to regler for suksess:
1. Fortell aldri alt du vet.
- Roger H. Lincoln
Dec 4 '06 #11

This discussion thread is closed

Replies have been disabled for this discussion.