Moving vector pointer to derived class of vector in C++? - c++

I want to move the pointer of a vector to my the vector of the A object (this). I want to do this because I use my help vector (for mergesort) and I want the values of the help vector in the original vector. I however only want to use 1 operation (so it should be done with a move, no copying of elements).
This is the code I use:
template<class T>
class A:public vector<T> {
public:
void fillAndMove();
vector<T> help;
}
template<class T>
void A<T>:fillAndMove() {
// Fill a help array with random values
help.resize(2);
help[0] = 5;
help[1] = 3;
// This line doesn't work
*this = move(help);
}
I get following error:
no match for 'operator=' (operand types are 'A<int>' and 'std::remove_reference<std::vector<int, std::allocator<int> >&>::type {aka std::vector<int, std::allocator<int> >}')
I think the problem is that the help vector needs to be casted to a class A object but I don't know how I should do it. Anyone that can help me?

You want to implement move assigment operator, which will do it in O(1).
template<class T>
class A :public vector<T> {
public:
void fillAndMove();
vector<T> help;
A & operator=(std::vector<T> && rhs)
{
static_cast<vector<T>&>(*this) = move(rhs);
return *this;
}
};
It will allow to assign normal vectors to your A class as well though, which will keep help vector unchanged, thus you might want to make this operator private and implement move assigment operator for A class public.
test = std::vector<int>{ 5,6 }; // possible - should assigment operator be private?
Not possible with this code:
template<class T>
class A :public vector<T> {
public:
void fillAndMove();
vector<T> help;
A & operator=(A && rhs)
{
// Move as you want it here, probably like this:
help = std::move(rhs.help);
static_cast<vector<T>&>(*this) = move(rhs);
return *this;
}
private:
A & operator=(std::vector<T> && rhs)
{
static_cast<vector<T>&>(*this) = move(rhs);
return *this;
}
};
Also, when doing it you should implement move constructor as well.

You have to overload operator assignment if you want to use it that way
A & operator=(const std::vector<T> & rhs)
{
for(auto it : help)
{
this->push_back(it);
}
return *this;
}
Working example here.

Related

performing function with classes of similar type C++

I want to implement a representation of matrices.
for that I have two types of matrices - regular and sparse, which differ in their
implementation - one holds a vector, and the second a map of indices and value,
both inherit from Matrix class.
I want to implement the + operator, which operates on Matrix and receives another Matrix.
but when I implement the + operator, I might receive as parameter sparse/regular matrix.
is there any way to receive a matrix, which I don't know what type of the 2 it is,
and perform the + operator?
meaning, if in class SparseMatrix I receive sparse/regular matrix, how can I implement the operator such that no matter which of the two types I get, it will work?
Matrix & operator+ (Matrix other)
{
...
}
I would probably implement two versions of operator+, and let them call a helper template method:
template <typename ITER>
Matrix add (ITER other_it) {
//...
}
Matrix operator+ (RegularMatrix other)
{
return add(other.begin());
}
Matrix operator+ (SparseMatrix other)
{
return add(other.begin());
}
You could make operator+ a template, but this way makes sure you only allow those Matrix types.
As was pointed out to me, you should not return a reference from +, as the result needs to be point to an instance that exists after the operation returns.
We can use polymorphism to create different implementations of a Matrix. Through the common interface of Matrix, each implementation can interact.
class Matrix
{
class iterator { ... }
friend Matrix operator+(const Matrix &lhs, const Matrix &rhs)
{
// iterate, add, and return new matrix
}
};
class SpareMatrix : public Matrix
{
iterator begin() { ... }
};
class Matrix
{
public:
virtual ~Matrix() {}
virtual Matrix& operator+(Matrix& other) = 0;
};
class MatrixSparse : public Matrix
{
public:
virtual ~MatrixSparse() {}
virtual Matrix& operator+(Matrix& other)
{
MatrixSparse* sparse = dynamic_cast<MatrixSparse*>(&other);
// TODO
}
};
class MatrixRegular : public Matrix
{
public:
virtual ~MatrixRegular() {}
virtual Matrix& operator+(Matrix& other)
{
MatrixRegular* regular = dynamic_cast<MatrixRegular*>(&other);
// TODO
}
};
Also, here is another SO thread dealing with the problem of overloading operators from abstract classes.

Initialising nested templates

I'm trying to learn more about templates and have come across a problem I can't seem to solve. At the moment the class below works fine.
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
template <class T, int s>
class myArray{
public:
T* data;
inline T& operator[](const int i){return data[i];}
myArray(){
data=new T[s];
}
myArray(const myArray& other){
data=new T[s];
copy(other.data,other.data+s,data);
}
myArray& operator=(const myArray& other){
data=new T[s];
copy(other.data,other.data+s,data);
return *this;
}
~myArray(){delete [] data;}
};
If I use it:
myArray<myArray<myArray<int,10>,20>,30> a;
a is now 30x20x10 array that I can access with the normal array brackets e.g. a[5][5][5]. I wish to add a feature so that I could write:
myArray<myArray<myArray<int,10>,20>,30> a(10);
and initialise all of the entries to 10 for example. I can't work out how to do this. As I understand, each layer of myArray is constructed using the default constructor. If I changed this to something like:
myArray(int n=0){
data=new T[s];
fill(data,data+s,n); //T might not be of type int so this could fail.
}
I think this should fail when data is not of type int (i.e. on any array on dimensions > 1), however it doesn't. It works when the array is square, but if not then some of the entries aren't set to 10. Does anyone have an idea how the standard vectors class achieves this? Any help would be amazing. Thanks!
Well, try something like this:
myArray()
: data(new T[s]()) // value-initialization!
{
}
myArray(T const & val)
: data(new T[s]) // default-initialization suffices
{
std::fill(data, data + s, val);
}
If you're into variadic templates, you might cook up something even more grotesque involving variadically filled initializer lists, but I think we've done enough learning for one week.
Note the fundamental flaw in using new: Either version requires that your class T can be instantiated in some "default" state, and that it be assignable, even though we never require the default state in the second version. That's why "real" libraries separate memory allocation and object construction, and you never see a new expression unless its the placement version.
std::vector uses placement new on memory blocks. It constructs the data.after allocating the memory in a second line of code.
This technique would work for you as well. Be careful with placement new as it requires you to call destructors manually as well.
Here is a half-assed route without placement new:
template<typename U>
explicit MyArray( U const& constructFromAnythingElse )
{
AllocateSpace(N); // write this, just allocates space
for (int i = 0; i < N; ++i)
{
Element(i) = T( constructFromAnythingElse );
}
}
with placement new, you have to allocate the memory first, then construct in-place, and then remember to destroy each element at the end.
The above is half-assed compared to a placement new route, because we first construct each element, then build another one, and use operator= to overwrite it.
By making it a template constructor on an arbitrary type, we don't rely on multiple conversion to get multiple levels down into the array. The naive version (where you take a T const&) doesn't work because to construct an array of arrays of arrays of T, the outermost one expects an array of arrays of T as an argument, which expects an array of T as an argument, which expects a T -- there are too many levels of user defined construction going on there.
With the above template constructor, the array of array of array of T accepts any type as a constructor. As does the array of array of T, as does the array of T. Finally, the T is passed in whatever you constructed the outermost array of array of array of T, and if it doesn't like it, you get a compiler error message that is nearly completely unreadable.
Make specialization for arrays containing other arrays. To do this you need some common implementation class to be used in general and specialized MyArray:
Common implementation (I made some fixes for you - see !!! comments):
template <class T, int s>
class myArrayImpl {
public:
T* data;
T& operator[](int i){return data[i];} //!!! const before int not needed
const T& operator[](int i) const {return data[i];} //!!! was missing
myArrayImpl(){
data=new T[s]();
}
myArrayImpl(const myArrayImpl & other){
data=new T[s];
copy(other.data,other.data+s,data);
}
myArrayImpl& operator=(const myArrayImpl& other){
T* olddata = data; // !!! need to store old data
data=new T[s];
copy(other.data,other.data+s,data);
delete [] olddata; //!!! to delete it after copying
return *this;
}
~myArrayImpl(){delete [] data;}
};
Then make general implementation - note the definition of value_type and setAll:
template <class T, int s>
class myArray : private myArrayImpl<T,s> {
typedef myArrayImpl<T,s> Impl;
public:
using Impl::operator[];
myArray() : Impl() {}
typedef T value_type; // !!!
explicit myArray(const value_type& value) {
setAll(value);
}
void setAll(const value_type& value) {
fill(this->data, this->data + s, value);
}
};
And the specialized version for myArray of myArray - see also differences in value_type and setAll:
template <class T, int s1, int s2>
class myArray<myArray<T,s2>,s1> : private myArrayImpl<myArray<T,s2>,s1> {
typedef myArrayImpl<myArray<T,s2>,s1> Impl;
public:
using Impl::operator[];
myArray() : Impl() {}
typedef typename myArray<T,s2>::value_type value_type; // !!!
explicit myArray(const value_type& value) {
setAll(value);
}
void setAll(const value_type& value) {
for_each(this->data, this->data + s1, [value](myArray<T,s2>& v) { v.setAll(value); });
}
};
And usage:
int main() {
myArray<myArray<myArray<int,7>,8>,9> a(7);
std::cout << a[0][0][0] << std::endl;
std::cout << a[8][7][6] << std::endl;
}
Full example here: http://ideone.com/0wdT9D

struct with const member

I'm having some trouble with a template struct.
template<typename T>
struct A{
const int v1;
T* v2;
};
My purpose is to make v1 always not editable, while v2 should be editable if I use T and not editable if I use const T as type.
If I create constructor to initialize A, the struct becomes:
template<typename T>
struct A{
const int v1;
T* v2;
A() : v1(-1) { v2=NULL; }
A(int value) : v1(value) { v2=NULL; }
};
But then g++ says that I need a specific assignment operator:
error: non-static const member ‘const int A::v1’, can’t use default assignment operator
But my assignment operator should also allow editing of v1. The only thing I'd like to avoid is an edit from the outside, something like:
A a;
a.v1=10;
Is there any way to implement this (without creating getter/setter or using a pointer to a new A(int) with the desired value)?
What if I declare v1 as a const int * ? It could refer someway to some value, but it cannot edit it.
Here's a way to "expose" a public, read-only data member that is modifiable by the class's own member functions (including assignment):
template <typename T>
class Helper {
friend class A;
T *ptr;
Helper &operator=(const Helper &rhs) = default; // in C++11
Helper &operator=(const Helper &rhs) { ptr = rhs.ptr; } // in C++03
public:
Helper(T *ptr) : ptr(ptr) {}
operator const int &() const { return *ptr; }
};
class A {
int v1_;
public:
Helper<int> v1;
A() : v1(&v1_) {} // although `A` should have a constructor that sets `v1_`
A(const A &rhs) { v1_ = rhs.v1_; v1 = Helper<int>(&v1_); }
A &operator=(const A &rhs) { v1_ = rhs.v1_; v1 = Helper<int>(&v1_); }
};
Now anyone outside the class A can use v1, but the only thing they can use it for is to get a const int& reference to v1_.
It is far easier just to give A a getter function that returns const int &, but if you really want the data member syntax then this provides it...
It says that you cannot use the default assignment operator. Nothing keeps you from writing your own operator= and use a const_cast. Unfortunately, this will be undefined behavior as v1 is declared const. So I'd suggest that you use accessors and private data.
You could just make it a class with everything public (thats all a struct is) and use an initialisation list - no need for getters/setters
I solved my problem by changing the type of v1 from int to const int *, by doing this I can change the address of v1 and consequently change the value that v1 points to, but preventing any kind of editing.
So, here's my new simple struct
template<typename T>
struct A{
const int* v1;
T* v2;
};
When I use A with type T, I let v2 to be edited, and when I use A with type T const I prevent any attempt to edit v2's pointed value.

When would I need to implement operator [] ?

given the following template function :
template <class T>
void DoSomething(T &obj1, T &obj2)
{
if(obj1 > obj2)
cout<<"obj1 bigger: "<<obj1;
else if(obj1 == obj2)
cout<<"equal";
else cout<<"obj2 bigger: "<<obj2;
T tmp(3);
T array[2];
array[0]=obj1;
array[1]=obj2;
}
I need to define a class called MyClass (declarations only , i.e. just the .h file) , that would be able to work with that template function .
I defined the next declarations :
class MyClass
{
public:
MyClass(); // default ctor
MyClass(int x); // for ctor with one argument
bool operator ==(const MyClass& myclass) const;
bool operator >(const MyClass& myclass) const;
friend ostream& operator<<(ostream &out,const MyClass& myclass); // output operator
};
What I don't understand is why there is no need to define operator [] for the lines:
array[0]=obj1; array[1]=obj2;
? When would I need to define operator []?
thanks ,Ron
You declared an array for your type:
T array[2];
But your are talking about implementing operator[] for T, which is totally different concept.
If you need
T t;
t[1] = blah
Then you need to implement operator[]
Because
T array[2];
Isn't a T object, its an array of T. So
array[0];
Is indexing an array, not one of your objects, therefore you don't need an operator[].
Assuming you call DoSomething with a couple of MyClass objects, you have declared array to be a normal array of MyClass objects. You did not need a [] operator for MyClass because array is not an instance of MyClass; it is just an array.
You will want to overload the [] operator in your own classes when it makes sense to, or is convenient. A good example is a collection (such as a map). Another example is a custom string class, where you might want to index by a regex object to find matches for your pattern inside your string.
If your class was an implementation of a dynamic array, for example, you would want to access the (single) object as though it was an array - you this by overloading the [] operator.

C++ STL question related to insert iterators and overloaded operators

#include <list>
#include <set>
#include <iterator>
#include <algorithm>
using namespace std;
class MyContainer {
public:
string value;
MyContainer& operator=(const string& s) {
this->value = s;
return *this;
}
};
int main()
{
list<string> strings;
strings.push_back("0");
strings.push_back("1");
strings.push_back("2");
set<MyContainer> containers;
copy(strings.begin(), strings.end(), inserter(containers, containers.end()));
}
The preceeding code does not compile. In standard C++ fashion the error output is verbose and difficult to understand. The key part seems to be this...
/usr/include/c++/4.4/bits/stl_algobase.h:313: error: no match for ‘operator=’ in ‘__result.std::insert_iterator::operator* [with _Container = std::set, std::allocator >]() = __first.std::_List_iterator::operator* [with _Tp = std::basic_string, std::allocator >]()’
...which I interpet to mean that the assignment operator needed is not defined. I took a look at the source code for insert_iterator and noted that it has overloaded the assignment operator. The copy algorithm must uses the insert iterators overloaded assignment operator to do its work(?).
I guess that because my input iterator is on a container of strings and my output iterator is on a container of MyContainers that the overloaded insert_iterator assignment operator can no longer work.
This is my best guess, but I am probably wrong.
So, why exactly does this not work and how can I accomplish what I am trying to do?
What would work would be using the constructor (which would make more sense instead of the assignment):
class MyContainer {
public:
string value;
MyContainer(const string& s): value(s) {
}
};
Then the second problem is that set also requires its contents to be comparable.
As to the cause, insert_iterator works by overloading operator=:
insert_iterator<Container>& operator= (typename Container::const_reference value);
As you can see, the righthand value must be either the value type of the container or implicitly convertible to it, which is exactly what a (non-explicit) constructor achieves and the assignment operator doesn't.
Technically you could also make it work without changing the class (e.g if you don't want an non-explicit constructor) by providing a suitable conversion function:
MyContainer from_string(const std::string& s)
{
MyContainer m;
m = s; //or any other method how to turn a string into MyContainer
return m;
}
which can be used with std::transform:
transform(strings.begin(), strings.end(), inserter(containers, containers.end()), from_string);
You need to add:
1. Constructor that takes string (you are trying to add string to container that can contain MyContainer objects).
2. bool operator < (set uses it by default to compare elements)
For instance :
class MyContainer
{
public:
MyContainer(const string& v):value(v){};
};
bool operator <(const MyContainer &c1, const MyContainer &c2)
{
return c1.value <c2.value;
}
The problem is twofold:
You're trying to fill a set of MyContainer objects
... from a list of string objects.
The copy() algorithm tries to convert each string object to a MyContainer object. In C++ to add to class MyContainer conversion support from type string to type MyContainer you need to add a constructor that takes a parameter of type string:
struct MyContainer {
MyContainer(const string& s) : value(s) { }
bool operator<(const MyContainer& o) const { return value < o.value; }
private:
string s;
};
You don't need an assignment operator, because the compiler can get the copying done by the copy-constructor: convert a string to a MyContainer and then use the default assignment operator to assign one MyContainer object onto the other. You will, however need an operator<() because C++ sets are sorted.