How can you define a copy constructor for a union? - c++

i am trying to define a copy constructor for unions but i don't know how to do it. Does anyone know how?
Here is an example:
struct apple {
string origin;
};
struct pear {
string origin;
};
union fruit {
fruit() {
}
~fruit() {
}
fruit(const fruit& other) {
}
fruit& operator=(const fruit& rhs) {
return *this;
}
apple apple;
pear pear;
};
How can the assignment operator and copy constructor be solved? Thanks!

Using an std::variant instead works. Here is the example fixed.
struct apple {
string origin;
};
struct pear {
string origin;
};
typedef variant<apple, pear> fruit;

Related

Move constructor c++

What's the right way to do a move constructor ?
class A{
...some stuff...
private:
int i;
std::string str;
};
A::A(A &&a)
{
*this = std::move(a);
};
or
A::A(A &&a)
{
this->str = std::move(a.str);
};
In the second case, is it useful to std::move() the int value ?
It should be
A::A(A&& other)
: i{other.i},
str{std::move(other.str)} {
// nop
}
This is the default implementation for a move constructor.

Struct in Class brings up error when class is used in array

When trying to create an array of my class, I was getting an error, so I started removing variables in the class. I found that removing all the structs named vector2, the compiler would be able to create an array of the class. I don't know why it doesn't work, or why a struct would affect it.
#include <iostream>
using namespace std;
struct vector2
{
double x = 0, y = 0;
vector2(double doubleX, double doubleY)
{
x = doubleX;
y = doubleY;
}
};
class Dog
{
private:
vector2 location;
int age;
public:
void setLocation(vector2);
vector2 getLocation();
void setAge(int);
int getAge();
};
void Dog::setLocation(vector2 newLocation)
{
location = newLocation;
}
vector2 Dog::getLocation()
{
return location;
}
void Dog::setAge(int newAge)
{
age = newAge;
}
int Dog::getAge()
{
return age;
}
int main()
{
Dog myDogs[1];
myDogs[0].setAge(10);
return 0;
}
BTW: I noticed some of the vector2 code doesn't work, but I've tried this using a std::vector, and it works perfectly (with a constructor)
Your Dog has a vector2 member variable, but vector2 doesn't have a default constructor. And you don't have a Dog constructor that uses vector2's parametrized constructor.
Either give vector2 a default constructor
vector2::vector2() : x{0.0}, y{0.0} {}
Or have a constructor for Dog that uses the parametrized constructor of vector2
Dog::Dog(int _age) : age{_age}, location{0.0, 0.0} {}

I want a vector of derived class pointers as base class pointers

In C++, the vector class stores an array of objects. In this case, I am storing pointers to derived class objects (Dogs). At some point, I want to treat this vector as pointers to objects of the base class (Animals). This is the "right"/non controversial way right? Why can't I do this?
#include <vector>
using namespace std;
class Animal { };
class Dog : public Animal { };
int main(int argc, char *argv[]) {
vector<Dog*> dogs;
dogs.push_back(new Dog());
dogs.push_back(new Dog());
vector<Animal*> animals = dogs; // This doesn't seem to work.
// This is really what I want to do...
vector<Animal*> all_animals[] = {dogs, cats, birds};
}
The error:
Untitled.cpp:11:18: error: no viable conversion from 'vector<class Dog *>' to 'vector<class Animal *>'
vector<Animal*> animals = dogs;
^ ~~~~
/usr/include/c++/4.2.1/bits/stl_vector.h:231:7: note: candidate constructor not viable: no known conversion from 'vector<Dog *>' to 'const std::vector<Animal *, std::allocator<Animal *> > &' for 1st argument
vector(const vector& __x)
^
There is a copy constructor for a std::vector but it requires you to copy the exact same type of vector. Fortunately, there is another constructor which takes a pair of iterators and adds all the elements in the range, so you can do this:
vector<Animal*> animals(dogs.begin(),dogs.end());
This creates a new vector of Animal pointers by iterating through each Dog pointer. Each Dog pointer is converted to an Animal pointer as it goes.
Here is a more complete example (using C++11):
#include <vector>
struct Animal { };
struct Dog : Animal { };
struct Cat : Animal { };
struct Bird : Animal { };
int main(int,char**)
{
Dog dog1, dog2;
Cat cat1, cat2;
Bird bird1, bird2;
std::vector<Dog *> dogs = {&dog1,&dog2};
std::vector<Cat *> cats = {&cat1,&cat2};
std::vector<Bird *> birds = {&bird1,&bird2};
std::vector<std::vector<Animal *>> all_animals = {
{dogs.begin(),dogs.end()},
{cats.begin(),cats.end()},
{birds.begin(),birds.end()}
};
}
You can do what you really want to do with no problems at all! That is, simply do:
class Animal {
public:
std::string GetNoise() const = 0;
};
class Dog : public Animal {
public:
std::string GetNoise() const { return "Bark!"; }
};
class Cat : public Animal {
public:
std::string GetNoise() const { return "Meow"; }
bool LikesSleeping() const { return true; }
};
Dog* d = new Dog;
Cat* c = new Cat;
vector<Animal*> all_animals;
all_animals.push_back(d, c);
// then, later...
// this will print "Bark!"
std::cout << all_animals[0]->GetNoise() std::endl;
// if you know the type somehow
Cat* x = dynamic_cast<Cat*>(all_animals[1]);
const bool y = x->LikesSleeping();
The reason that your code didn't work the way you expect is that: std::vector<Dog*> is a totally different class from std::vector<Animal*>.
In other words, Dog inherits from Animal, yes, but a std::vector<X> does not inherit from std::vector<Y> -- no matter how X and Y are related!
Templates don't give the vector much intelligence; they just define a new class. You can think of it this way:
class vectorOfDogs {
Dog* myDogs;
//...
}
class vectorOfAnimals {
Animal* myAnimals;
//...
}
Does vectorOfDogs inhert from vectorOfAnimals? Clearly not! But all that's been done is changing the name of the class from std::vector<Dog*> to vectorOfDogs.
The accepted solution is fine, but has one big drawback: It maintains copies of the contents of the vectors in question. Any time one of the vectors is updated, we need to update the redundant data as well to keep global state consistent. Not being very fond of, decided to try to get around this issue (unfortunately needed to discover that this requires quite some work...):
class AllAnimals
{
struct Wrapper
{
virtual ~Wrapper() { }
virtual Animal* begin() = 0;
virtual Animal* end() = 0;
};
template <typename T>
struct SpecificWrapper : Wrapper
{
T& animals;
SpecificWrapper(T& animals)
: animals(animals)
{ }
Animal* begin() override
{
return *animals.begin();
}
Animal* end() override
{
return *animals.end();
}
};
std::vector<std::unique_ptr<Wrapper>> wrappers;
public:
class iterator : public std::iterator<std::forward_iterator_tag, Animal*>
{
friend class AllAnimals;
decltype(wrappers)::iterator current, end;
Animal* animal;
iterator(decltype(current) begin, decltype(end) end)
: current(begin), end(end)//, animal(nullptr)
{
while(current != end && (*current)->begin() == (*current)->end())
{
++current;
}
animal = current == end ? nullptr : (*current)->begin();
}
public:
bool operator==(iterator const& other)
{
return current == other.current && animal == other.animal;
}
bool operator!=(iterator const& other)
{
return !(*this == other);
}
iterator& operator++()
{
if(++animal == (*current)->end())
{
++current;
animal = current == end ? nullptr : (*current)->begin();
}
return *this;
}
iterator operator++(int)
{
iterator i(*this);
++*this;
return i;
}
Animal* operator*()
{
return animal;
}
Animal* operator->()
{
return animal;
}
};
iterator begin()
{
return iterator(wrappers.begin(), wrappers.end());
}
iterator end()
{
return iterator(wrappers.end(), wrappers.end());
}
template <typename T>
void push_back(std::vector<T*>& v)
{
wrappers.emplace_back(new SpecificWrapper<decltype(v)>(v));
}
};
I only implemented a forward iterator so far, one could provide further operators to make a bidirectional or even random access one from. Additionally, we might add const iterators, (const) reverse iterators, ...
You may Create your Dog Vector as:
vector<Animal*> dogs;
And cast your dog objects before inserting them
dogs.push_back((Animal*)new Dog());
Later, cast back while accessing

Class inheritance - stacking methods

I have seen this once, but I can't remember how to make it work again. Let's say I have three classes:
class CRoot { ... };
class CLevelOne { ... };
class CLevelTwo { ... };
Now, I have main function, where I'd like to go more in depth by using this syntax:
int main (void)
{
CRoot myRoot ("This is root.");
myroot.AddLevelOne("This is level one.").AddLevelTwo("This is level two.");
}
So the final construction of my classes looks like this:
+- This is root.
|+- This is level one.
||+- This is level two.
How to implement it so I can use syntax something.Method1().Method2().MethodN(). ...; ?
Try this:
struct Level2
{
// See class Level1 below
};
struct Level1
{
std::string m_name;
boost::shared_ptr<Level2> p_level2;
Level1(const std::string name)
: name(m_name)
{ ; }
Level2& add_level_two(const std::string& name)
{
p_level2 = new Level2(name);
}
};
struct Root
{
boost::shared_ptr<Level1> p_level1;
Level1& add_level_one(const std::string& name)
{
p_level1 = new Level1(name);
}
};
With a little more thought, a base class, one could create this more generically. Also the level numbers would have to be moved out of the method names.
Something like this:
struct CLevelTwo { };
struct CLevelOne {
CLevelTwo * AddLevelTwo() {
return new CLevelTwo();
}
};
struct CRoot {
CLevelOne * AddLevelOne() {
return new CLevelOne();
}
};
int main(){
CRoot *root = new CRoot();
root->AddLevelOne()->AddLeveTwo();
}
You can replace the pointers with references, but beware of memory leaks. Note that this code leaks too, but it is more manageable and managing lifetime of the objects should not be a big problem.
Just make SomeMethod return a reference of *this:
struct Foo
{
Foo& Add(SomeOtherThing& thing)
{
// Do the "add"...
return *this;
}
};
Now you can do:
Foo myFoo;
myFoo.Add(...).Add(...).Add(...);
It's just like how the assignment operator overload works.
Edit After reviewing this with Thibaut, I propose the following solution:
class Node
{
private:
std::string _name;
std::list<Node*> _nodes;
public:
Node(const std::string& name) : _name(name)
{
}; // eo ctor
virtual ~Node()
{
for(std::list<Node*>::iterator it(_nodes.begin());
it != _nodes.end();
++it);
delete *it;
}; // eo dtor
Node* Add(const std::string& name)
{
Node* newNode = new Node(name);
_nodes.Add(newNode);
return newNode;
}; // eo Add
}; // eo class Node

Freeing resources in a class with shared pointers

I have a class like the following:
class A {
SuperHugeClass* s;
public:
A(){ s = new SuperHugeClass(); }
};
Because SuperHugeClass takes a lot of memory, I'm fine with the shallow copying provided by the default constructor and assignment operator. However, I also don't want to leak memory, so I need to delete s, but I have to be careful about it because otherwise I'll delete it more than once.
One way of doing this is by refcounting s as follows:
class A {
int* refcount;
SuperHugeClass* s;
public:
A(){
refcount = new int(1);
s = new SuperHugeClass();
}
A(const A& other) : refcount(other.refcount), s(other.s) {
(*refcount)++;
}
~A() {
(*refcount)--;
if (!(*refcount)) {
delete refcount;
delete s;
}
}
friend void swap(const A& a, const A& aa) {
std::swap(a.refcount, aa.refcount);
std::swap(a.s, aa.s);
}
A& operator=(A other) {
swap(*this, other);
return (*this);
}
};
This is the first time I've needed to do something like this, but it seems to me that this should be pretty standard and so there should be a 'canonical' solution. Are there any other ways of doing this? Thanks!
Use std::shared_ptr
class A {
std::shared_ptr<SuperHugeClass> s;
public:
A()
: s(new SuperHugeClass())
{
}
};
and thats it. Default generated copy constructor/assignment operator/destructor do just what you need.
Use std/boost::shared_ptr instead of your ref-counted pointer.