C++ Creating a Matrix of Sets - c++

I am trying to create a Matrix of Sets in C++ but I get an error that there is no matching function to call. Here is my code:
supermercat.hh
#ifndef SUPERMERCAT_HH
#define SUPERMERCAT_HH
#include <vector>
#include <iostream>
#include <set>
#include "producte.hh"
using namespace std;
class supermercat
{
private:
vector <vector <set <producte> > > estructura;
public:
// Constructores
supermercat();
//Modificadores
void crear_estructura(int col, int fil);
void repostar_estanteries(producte prod, string lloc);
supermercat.cc
#include "supermercat.hh"
supermercat::supermercat() {}
void supermercat::crear_estructura(int col, int fil)
{
vector <vector <set <producte> > > estructura(col, vector<producte>(fil));
}
void supermercat::repostar_estanteries(producte prod, string lloc)
{
estructura[lloc[0] - 'A'][lloc[1] - 1].insert(prod);
}
Does anyone know what I am doing wrong? I just can't figure it out.
I tried to do it as a matrix of vectors in the past but it as kind of annoying to sort each vector in the matrix (as I need 'productes' to be ordered alphabetically).

I think that the problem is your crear_estructura method implementation. In the base class (supermercat), you have the private member:
vector <vector <set <producte> > > estructura;
In the implementation part, you try to execute following:
vector <vector <set <producte> > > estructura(col, vector<producte>(fil));
and it is not defined elsewhere (to me, this line is a declaration, it does not implement anything).
Also, the input:
vector<producte>(fil)
in previous definition is rather strange. Did you mean to use square brackets, i.e. [] instead of ()? E.g. vector<producte> prods[fill].
As your solution is somewhat tricky, I'd suggest to simplify it a bit. The quick solution is to make a new class estructura (fill in as appropriate):
class estructura
{
private:
vector <vector <set <producte> > > _mestruct;
public:
estructura(int col, vector<producte> fil);
~estructura();
}
and then implement constructor to fit your requirements. After that, use it in the supermercat class like this:
class supermercat
{
private:
estructura structdata;
public:
... (like before)
}
and your supermercat constructor implementation should be like this:
void supermercat::crear_estructura(int col, vector<producte> fil)
{
estructura(col, fil);
}
I hope this will help you a bit to solve the problem.

The problem you have is with the vector initialization, you should use resize() to resize the first dimension and then resize for each item to resize the other dimension of the vector, here is a simple example that does that:
#include <iostream>
#include <vector>
#include <set>
std::vector< std::vector< std::set<int> > > test;
int main()
{
test.resize(100);
// if not c++11 replace with for (i = 0; i < 100; ++i) test[i].resize(100)
for (auto &a: test)
a.resize(100);
test[20][20].insert(1);
test[30][30].insert(1);
test[30][30].insert(2);
std::cout << "(20,20): " << *test[20][20].begin() << std::endl;
std::cout << "(30,30): size " << test[30][30].size() << std::endl;
}
Using this syntax in your "create_estructura" method it should be something like:
void supermercat::crear_estructura(int col, int fil)
{
estructura.resize(col);
for (auto &a: estructura) a.resize(fil);
}
Every item in "estructura" will contain an empty set.

Related

Double declaration and initialization of vector in a class, C++?

Good night dear all
I have a question, look i working with classes and in many cases i am using vectors of vector (2D vectors), my code runs quite well. However, i am a bit confused, look in my header file i declared a vector of vectors in my protected variables, then in my cpp file in the constructors section i declared again the vector of vectors, but this time giving the needed sizes and having "0" in all the elements. However, when i tried to use this vector of vectors in my member function, it seems that not dimension was delcared and not "0" values, if i use .size() the output is "0" and i was expecting 3.
However, when i declare again the vectors of vectors in the member (see commented line in the cpp file) function the code gives the 3 and the full matrix which is a 3 X 3, composed by "0".
Why is that? using the constructor is to bassically give the values of the variables.
See the next code, the commented line on the cpp file is on which i have declare again the vector.
the header file is:
#pragma once
#include <iostream>
#include <vector>
class Matrix
{
private:
const int m_nRows;
const int m_nCols;
protected:
std::vector <std::vector <double>> MATRIX;
public:
Matrix(int rows, int cols);
~Matrix();
void getMatrix();
};
The cpp file is:
#include "Matrix.h"
Matrix::Matrix(int rows, int cols)
: m_nRows(rows),
m_nCols(cols)
{
std::vector <std::vector <double>> MATRIX(m_nRows, std::vector<double>(m_nCols, 0));
}
Matrix::~Matrix()
{
}
void Matrix::getMatrix()
{
//std::vector <std::vector <double>> MATRIX(m_nRows, std::vector<double>(m_nCols, 0));
std::cout << MATRIX.size() << std::endl;
for (auto& columns : MATRIX)
{
for (auto& element : columns)
{
std::cout << element << " ";
}
std::cout << "\n";
}
}
The main file is:
#include <iostream>
#include <vector>
#include "Matrix.h"
int main() {
int rows = 3;
int cols = 3;
Matrix SmallMatrix(rows, cols);
SmallMatrix.getMatrix();
system("pause>0");
}
In your constructor:
Matrix::Matrix(int rows, int cols)
: m_nRows(rows),
m_nCols(cols)
{
std::vector <std::vector <double>> MATRIX(m_nRows, std::vector<double>(m_nCols, 0));
}
you define a brand new variable with the name MATRIX, which is totally distinct from the member variable Matrix::MATRIX.
To initialize the Matrix::MATRIX member variable you should do it in the member initializer list, jut like for the m_nRows and m_nCols variables:
Matrix::Matrix(int rows, int cols)
: m_nRows(rows),
m_nCols(cols),
MATRIX(m_nRows, std::vector<double>(m_nCols, 0))
{
}
You are declaring another variable named MATRIX in the constructor. You have to instead use resize() on the MATRIX member declared in the class. The initialization of that MATRIX can be like this:
MATRIX.resize(m_nRows);
for (int i =0; i<m_nRows; i++){
MATRIX[i].resize(m_nCols, 0);
}

How to make a C++ map with class as value with a constructor

I have a class that has a constructor. I now need to make a map with it as a value how do I do this? Right now without a constructor I do.
#include <iostream>
#include <map>
using namespace std;
class testclass {
public:
int x = 1;
};
int main()
{
map<int,testclass> thismap;
testclass &x = thismap[2];
}
If I added a constructor with arguments how would I add them to the map? I basically need to do
#include <iostream>
#include <map>
using namespace std;
class testclass {
public:
int x = 1;
testclass(int arg) {
x = arg;
}
};
int main()
{
map<int,testclass> thismap;
testclass &x = thismap[2];
}
This obviously wouldn't work since it requires an argument but I can't figure a way of doing this.
This is how you can add items of your own class to your map.
Note : I used a string in testclass to better show difference
between key and value/class.
#include <iostream>
#include <string>
#include <map>
class testclass
{
public:
explicit testclass(const std::string& name) :
m_name{ name }
{
};
const std::string& name() const
{
return m_name;
}
private:
std::string m_name;
};
int main()
{
std::map<int, testclass> mymap;
// emplace will call constructor of testclass with "one", and "two"
// and efficiently place the newly constructed object in the map
mymap.emplace(1, "one");
mymap.emplace(2, "two");
std::cout << mymap.at(1).name() << std::endl;
std::cout << mymap.at(2).name() << std::endl;
}
Using std::map::operator[] requires that the mapped type is default-constructible, since it must be able to construct an element if one doesn't already exist.
If your mapped type is not default-constructible, you can add elements with std::map::emplace, but you still can't use std::map::operator[] to search, you will need to use std::map::find() or so.
That's a rather obvious feature of std::map (and very similar other std containers). Some of their operations require specific type requirements for good reasons.
There is no problem to create such a map as you suggest in the first place, however, you are restricted to method calls that do not require potential default construction. The operator[] is such a method, since in the case the element is not found, it is created. That is what does not work in your example. Just use other methods with little impact on the map usage and you can still succeed:
#include <iostream>
#include <map>
using namespace std;
class testclass {
public:
int x = 1;
testclass(int arg) {
x = arg;
}
};
int main()
{
map<int,testclass> thismap;
thismap.insert( {2, testclass(5)} );
auto element2 = thismap.find(2);
if (element2 != thismap.end()) {
testclass& thiselement = element2->second;
cout << "element 2 found in map, value=" << thiselement.x << endl;
}
auto element5 = thismap.find(5);
if (element5 == thismap.end()) {
cout << "no element with key 5 in thismap. Error handling." << endl;
}
}
Main issue: avoid operator[].
Note:
Looking at the other very good answers, there are a lot of methods that can be used without default construction. There is not "right" or "wrong" since this simply depends on your application. at and emplace are prime examples that are highly advisable.

How to most concisely initialize std::map using an initializer list that includes a constructor call for the mapped_type

The vector constructor calls in the statement below construct vectors with 50 elements of identical values in each vector as values in the sviMap. The statement repeats vector<int> three times. Is there a more concise way to achieve this overall initialization of the sviMap where vector<int> appears only once in the statement?
map<string, vector<int>> sviMap { {"Leo", vector<int>(50, 101)} , {"Brad", vector<int>(50, 201)} };
Strictly speaking, no. You need to have template specialization and two instances of the vector.
But if you need to have "this text once", this workaround could work for you:
using vi = vector<int>;
map<string, vi> sviMap{ {"Leo", vi(50, 101)} , {"Brad", vi(50, 201)} };
Formally, this is not "the statement", but two statements, but the vector appears only once. If your goal is to have one point for changes, this could work.
I wanted to correct my mistake, so here's another solution.
And this one will result in vectors of the correct length.
I just used inheritance to create a vector type with a constructor that has the desired behavior, so you can then use initializer lists without extra specifics
#include <cassert>
#include <map>
#include <vector>
#include <string>
template<typename type_t>
class my_vector :
public std::vector<type_t>
{
public:
my_vector() = default;
my_vector(const size_t size, const type_t value) :
std::vector<type_t>(size, value)
{
}
};
int main()
{
std::map<std::string, my_vector<int>> sviMap{ { "Leo", {50, 101}}, { "Brad", {50, 201}} };
auto vec = sviMap["Leo"];
auto value = vec[23];
}
You can do it like this, just use nested initializers
#include <map>
#include <vector>
#include <string>
int main()
{
std::map<std::string, std::vector<int>> sviMap
{
{"Leo", {50, 101}},
{"Brad", {50, 201}}
};
auto vec = sviMap["Leo"];
}

How to implement constructors of Class A that has a member variable vector <Class B>,which is its Base function, using initializer_list and template?

So the problems are:
Class Stan must have a constructor that enables it to recieve and store unlimited nubmer of elements and it has to be implemented using templates. Also, demonstrate it in the main function
Class Stan must have a constructor that enables it to recieve and store unlimited nubmer of elements and it has to be implemented using initializer lists. Also, demonstrate in main function
Place class Stan into the namespace Zgrada
Lets assume that there are 2 types of Stans - Apa & Gar. Within the main function it is necessary to demonstrate polimorphism by implementing getVrsta(); which returns one of the 2 types
I have no clue how to do more than this.
Thanks for the help!
#include <string>
#include <vector>
#include <functional>
#include <algorithm>
#include <iterator>
using namespace std;
int Element::brV = 0;
class Element {
public:
string naziv;
double obujam;
static int brV;
Element(string n, double o) : naziv(n), obujam(o) {
if (o > 3.) brV++;
}
int getVelikiElementi(){
return brV;
}
void virtual GetVrsta(){
cout << "Vrsta Stana: ";
}
};
template <class T> //I think i got the templates_init right
class Stan : public Element {
public:
vector<Element> Elementi;
template<class...T>
Stan(T...arg) : Elementi({arg...}){}
Stan(initializer_list<Elementi>) : Element (){} // But this most certainly not
void GetVrsta(){
}
};
int main () {
Element X("a", 3.);
Element Y("b", 2.);
Element Z("c", 1.);
vector <Element*> E={X,Y,Z}; // initilizer_lista_const_call
return 0;
}```

Declaring vector size in a class

I am supposed to write a program that simulates a dice(6 faced) roll 6000 times and stores the results in a vector. For example if the dice roll returns 1, I would do something like frequency.at(0)++. Since the size of the vector is gonna be fixed, and I would also need to able to access each element freely, I was wondering if there was anyway to declare the size of the vector using a default constructor or something. This is what I currently have but I get a "too many arguments in function call" and "expression must have class type" error. Maybe what I'm trying to do is not possible, I don't know, but just looking for some help. Thanks.
My header file:
#ifndef AHISTOGRAM_H
#define AHISTOGRAM_H
class aHistogram
{
public:
aHistogram();
~aHistogram();
void update(int face);
void display(int maxLengthOfLine);
void clear() const;
int count(int face);
private:
vector<int> numRolls();
int numx, m, j;
};
#endif
aHistogram.cpp:
#include <iostream>
#include <cstdlib>
#include <vector>
#include "aHistogram.h"
using namespace std;
aHistogram::aHistogram()
{
numRolls(6);
numx, m, j = 0;
}
aHistogram::~aHistogram()
{
}
void aHistogram::update(int face)
{
numRolls.at(face - 1)++;
return;
}
This is what the constructor's initializer list is for:
aHistogram::aHistogram(): numRolls(6), numx(0), m(0), j(0) // constructor parameters here
{
// numRolls(6);
// numx m, j = 0;
}
Also the declaration of your vector is wrong in your class definition:
class aHistogram
{
public:
aHistogram();
~aHistogram();
void update(int face);
void display(int maxLengthOfLine);
void clear() const;
int count(int face);
private:
// vector<int> numRolls(); // this is declaring a function!
vector<int> numRolls; // USE THIS!!
int numx, m, j;
};
IF the size of the "vector" is fixed, then using std::array is most certainly a better option, unless of course, you are using an ancient compiler which doesn't support C++11.
Go through the above link on cppreference.com. For most part, it is just like an "old fashioned" array, but it also comes with benefits such as bounds checking (if you use at() instead of operator[]), ability to iterate through elements (begin(), end(), etc.), and many other "benefits" of std::vector.
Have a look at this:
#include <iostream>
#include <array>
using namespace std;
class aHistogram {
public:
aHistogram() : numRolls{0, 0, 0, 0, 0, 0} {}
int count(int face) {
return numRolls.at(face - 1);
}
void update(int face) {
numRolls.at(face - 1)++;
}
private:
array<int, 7> numRolls;
};
int main() {
aHistogram ah;
ah.update(1);
ah.update(2);
ah.update(1);
cout << "Count[1]: " << ah.count(1) << " Count[2]: " << ah.count(2) << endl;
}