Shared_ptr is null on re-iteration in std::Vector - c++

I have the below program of an execution class which populates a map shown below
map<string,map<string,vector<StructAbsTypeObject>>>
Here I am making shared objects and assigning them which are valid during first check, but on second check shared_ptr returns null. I need to know the reason why. The code seems fine but don't know where is it going wrong.
//Code begins
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <memory>
using namespace std;
class Test {
public:
Test(int i):t(i) {
}
private:
int t;
};
class ConcTypeObject {
public:
ConcTypeObject() {
}
ConcTypeObject(const ConcTypeObject& other) {
m_ptr_Test = other.m_ptr_Test;
}
ConcTypeObject& operator=(const ConcTypeObject& other) {
m_ptr_Test = other.m_ptr_Test;
}
void setTest(shared_ptr<Test> ptr) {
cout << "setTest" << endl;
m_ptr_Test = ptr;
}
shared_ptr<Test> getTest() {
return m_ptr_Test;
}
bool isValid() {
if(m_ptr_Test) {
return true;
} else {
return false;
}
}
private:
shared_ptr<Test> m_ptr_Test;
};
class AbsTypeObject {
public:
explicit AbsTypeObject(const string str) {
m_str = str;
}
AbsTypeObject(const AbsTypeObject& other) {
m_str = other.m_str;
m_ptr_ConcTypeObject = other.m_ptr_ConcTypeObject;
}
AbsTypeObject& operator=(const AbsTypeObject& other) {
m_str = other.m_str;
m_ptr_ConcTypeObject = other.m_ptr_ConcTypeObject;
}
bool operator==(const AbsTypeObject& other) {
if(m_str == other.m_str)
return true;
else
return false;
}
void setConcTypeObject(shared_ptr<ConcTypeObject> ptr) {
m_ptr_ConcTypeObject = ptr;
}
shared_ptr<ConcTypeObject> getConcTypeObject() {
return m_ptr_ConcTypeObject;
}
bool isValid() {
if(m_ptr_ConcTypeObject) {
cout << "AbsTypeObject 1 " << endl;
return m_ptr_ConcTypeObject->isValid();
} else {
cout << "AbsTypeObject 2 " << endl;
return false;
}
}
private:
string m_str;
shared_ptr<ConcTypeObject> m_ptr_ConcTypeObject;
};
class StructAbsTypeObject {
public:
StructAbsTypeObject(const string str):m_AbsTypeObject(str) {
}
void SetAbsTypeObject(AbsTypeObject& id) {
m_AbsTypeObject = id;
}
AbsTypeObject& GetAbsTypeObject() {
return m_AbsTypeObject;
}
private:
AbsTypeObject m_AbsTypeObject;
};
class Executor {
public:
static Executor m_Executor;
static Executor& get() {
return m_Executor;
}
Executor() {
StructAbsTypeObject sid(std::string("ABCD"));
vector<StructAbsTypeObject> a_vecstid;
a_vecstid.push_back(sid);
m_executormap["ExecutorInterface"]["ExecutorName"] = a_vecstid;
}
void check() {
for(auto outermap : m_executormap) {
for(auto innermap : outermap.second) {
for(auto vec_element: innermap.second) {
if(vec_element.GetAbsTypeObject().isValid()) {
cout << "PTR VALID" << endl;
} else {
cout << "PTR NOT Valid" << endl;
}
}
}
}
}
void fillAbsTypeObject(AbsTypeObject &id) {
shared_ptr<Test> ptr_test = make_shared<Test>(20);
shared_ptr<ConcTypeObject> ptr_ConcTypeObject = make_shared<ConcTypeObject>();
id.setConcTypeObject(ptr_ConcTypeObject);
id.getConcTypeObject()->setTest(ptr_test);
}
void Init(AbsTypeObject id) {
for(auto outermap : m_executormap) {
for(auto innermap : outermap.second) {
for(auto vec_element: innermap.second) {
if(vec_element.GetAbsTypeObject() == id) {
cout << "Id Equal" << endl;
fillAbsTypeObject(id);
vec_element.SetAbsTypeObject(id);
if(vec_element.GetAbsTypeObject().isValid()) {
cout << "PTR VALID" << endl;
} else {
cout << "PTR NOT Valid" << endl;
}
}
}
}
check();
}
}
private:
using executormap = map<string,map<string,vector<StructAbsTypeObject>>>;
executormap m_executormap;
};
Executor Executor::m_Executor;
int main()
{
AbsTypeObject id(std::string("ABCD"));
Executor::get().Init(id);
}
//Code Ends
The above code is completely compilable and Runnable. Currently I am getting the following output
//Output Begins
Id Equal
setTest
AbsTypeObject 1
PTR VALID
AbsTypeObject 2
PTR NOT Valid
//Output Ends
The PTR NOT VALID is output when check function is executed. Expecting output is
PTR VALID in both cases.
Please let me know what is going wrong in the above code. I did try few things but did not work. If it does not work, what is the reason and what is the correct way to make it work.
Thanks in advance.

In your for loops:
for(auto outermap : m_executormap) {
for(auto innermap : outermap.second) {
for(auto vec_element: innermap.second) {
You are using auto which defaults to a non-reference type so you are taking a copy of each element in the map/vector. Your changes are being applied to these temporary copies so are lost.
Simply change these to references to update the original lists:
for(auto& outermap : m_executormap) {
for(auto& innermap : outermap.second) {
for(auto& vec_element: innermap.second) {

Related

Modifing an object by another class

My purpose is to change the tank (an object of first class) by another class (the odometer). So I try to passing by reference, its working when I pass directly object to constructor but its doesn't working when I make an object first then passing object by a method(setOdoIndex). Can someone have a way to do make a method to pass these parameters
#include <iostream>
using namespace std;
class FuelGauge {
protected:
double galls;
double check(double) const;
double checkFuel(double) const;
public:
FuelGauge(double galls){
check(galls);
this->galls = galls;
}
FuelGauge(){
*this = FuelGauge(0);
}
double getFuelLeft() const{
return galls;
}
FuelGauge operator++(){
if (galls > 15) throw "Tank max capacity is 15 gallon";
++galls;
return *this;
}
FuelGauge operator--(){
if (galls == 0) throw "Tank is empty";
--galls;
return *this;
}
void refuel(){
galls = 15;
}
};
double FuelGauge::check(double n) const {
if (n < 0) throw "Dont accepted negative value!";
if (n > 15) throw "Tank max capacity is 15 gallon";
return n;
}
class Odometer{
private:
int odo;
FuelGauge &tank;
void calOdo() {
if (odo > 999999) {odo = 0;};
}
public:
Odometer(int odo, FuelGauge &tank):tank(tank) {
this->odo = odo;
this->tank = tank;
}
Odometer():tank(tank) {
odo = 0;
}
int getOdoIndex() const{
return odo;
}
void setOdoIndex(int odo, FuelGauge &tank) {
this->odo = odo;
this->tank = tank;
}
void carDrive() {
--tank;
calOdo();
++odo;
}
};
int main() {
FuelGauge tank;
cout << "--Fill the tank--" << endl;
try {
for (int i = 0; i < 15; i++) {
++tank;
}
}
catch(const char* e) {
cerr << e << '\n';
}
cout << "\n--Car run--" << endl;
Odometer odo1(0, tank);
try {
for(int i = 0; i < 16; i++) {
cout << "Index of odometer: " << odo1.getOdoIndex() << endl;
cout << "Fuel left: " << tank.getFuelLeft() << endl;
odo1.carDrive();
}
}
catch(const char* e) {
cerr << e << '\n';
}
return 0;
}

Create a generator in C++ using coroutines

Following the McNellis's presentation for coroutines(Introduction to C Coroutines), I try to compile the example of the simple coroutine, which actually is a simple counter.
However when the resume is called ,assertion is fired.
Specifically
_LIBCPP_ASSERT(!done(),
"resume() has undefined behaviour when the coroutine is done");
I have not much experience with coroutines and I cannot find out what goes wrong.
The code is below
#include <iostream>
#include <coroutine>
using namespace std;
//using namespace experimental;
struct resumable_thing
{
struct promise_type
{
int const* _current;
promise_type & get_return_object() noexcept
{
return *this;
}
auto initial_suspend() { return suspend_always{}; }
auto final_suspend() { return suspend_always{}; }
auto yield_value(int const& value) {
_current = &value;
return suspend_always{};
}
void unhandled_exception()
{
auto ex = std::current_exception();
std::rethrow_exception(ex);
//// MSVC bug? should be possible to rethrow with "throw;"
//// rethrow exception immediately
// throw;
}
void return_void() noexcept
{
}
};
// using coroutine_handle = coroutine_handle<promise_type>;
resumable_thing() = default;
resumable_thing(resumable_thing const & ) = delete;
resumable_thing & operator = (resumable_thing const & ) =delete;
resumable_thing(promise_type && promise)
: _coroutine(coroutine_handle<promise_type>::from_promise(promise)) {}
resumable_thing(resumable_thing&& other) : _coroutine(other._coroutine)
{
other._coroutine = nullptr;
}
resumable_thing & operator = (resumable_thing const && other)
{
_coroutine = other._coroutine;
_coroutine = nullptr;
return *this;
}
explicit resumable_thing(coroutine_handle<promise_type> coroutine)
:_coroutine(coroutine)
{
}
~resumable_thing()
{
if(_coroutine)
{
_coroutine.destroy();
}
}
void resume()
{
std::cout << "coroutines resume" << std::endl;
_coroutine.resume();
}
coroutine_handle<promise_type> _coroutine = nullptr;
};
resumable_thing counter()
{
cout << "counter: called\n";
for(int i = 0 ; ++i;)
{
co_await suspend_always{};
cout << "counter: resumed (#" << i << ")\n";
}
}
int main(int argc, const char * argv[]) {
// insert code here...
cout << "main: calling counter\n";
resumable_thing the_counter = counter();
cout << "main: resuming counter\n";
the_counter.resume();//assertion is fired
cout << "main:done" << std::endl;
return 0;
}
Please find the code here
promise_type::get_return_object() shall return user-defined coroutine result type resumable_thing, instead of promise_type& itself.
struct resumable_thing
{
struct promise_type
{
resumable_thing get_return_object() noexcept
{
return {*this};
}
// ...
};
resumable_thing(promise_type & promise)
: _coroutine(coroutine_handle<promise_type>::from_promise(promise)) {}
// ...
};
And resumable_thing's move assignment operator resets this->_coroutine unintentionally.
// FIXED: resumable_thing const && -> resumable_thing &&
resumable_thing & operator = (resumable_thing && other)
{
_coroutine = other._coroutine;
// FIXED: _coroutine -> other._coroutine
other._coroutine = nullptr;
return *this;
}

How to test the given ADT implementation with templates such as <int, int> and <string, int>?

I am working on a problem that requires the implementation of two ADT's. After Implementing, I need to test my bag implementations with the following template combinations:
<int, string>-- all functions
<string, int> -- insert and find functions only
My testing so far has been entering integers to test the different functions. I do not understand what it means to test the implementations with the templates.
Here is my bagADT implementation:
#include <stdlib.h>
#include "bagADT.h"
template <typename E>
class ABag : public Bag<E> {
private:
int maxSize;
int listSize;
E* listArray;
public:
ABag(int size = defaultSize) { // Constructor
maxSize = size;
listSize = 0;
listArray = new E[maxSize];
}
~ABag() { delete[] listArray; } // Destructor
bool addItem(const E& item) {
if (listSize >= maxSize) {
return false;
}
listArray[listSize] = item;
std::cout << "Add Item: Added " << item << " in spot " << listSize << std::endl;
listSize++;
return true;
}
bool remove(E& item) {
for (int i = 0; i < listSize; i++) {
if (listArray[i] == item) {
std::cout << "Remove: Removed " << item << " from position ";
item = i;
std::cout<< item << " and adjusted the location of all other elements." << std::endl;
for (i= item; i < listSize; i++) {
listArray[i] = listArray[i + 1];
}
listSize--;
return true;
}
}
return false;
}
bool removeTop(E& returnValue) {
if (listSize == 0) {
return false;
}
else {
returnValue = listArray[listSize - 1];
std::cout << "Remove Top: Removed " << returnValue << " from the top of the stack." << std::endl;
for (int i = listSize; i < maxSize; i++) {
listArray[i] = listArray[i + 1];
}
listSize--;
return true;
}
}
bool find(E& returnValue) const {
for (int i = 0; i < (listSize - 1); i++) {
if (listArray[i] == returnValue) {
returnValue = i;
return true;
}
}
return false;
}
bool inspectTop(E& item) const {
if (listSize == 0) {
return false;
}
else {
item = listArray[listSize - 1];
std::cout << "Inspect Top: The value on top is currently " << item << "." << std::endl;
return true;
}
}
void emptyBag() {
delete[] listArray;
listSize = 0;
listArray = new E[maxSize];
std::cout << "Empty Bag: Emptied the bag." << std::endl;
}
bool operator+=(const E& addend) {
if (listSize < maxSize) {
return true;
}
return false;
}
int size() const {
std::cout << "Size: Number of elements in listArray: " << listSize << std::endl;
return (listSize - 1);
}
int bagCapacity() const {
std::cout << "Bag Capacity: The capacity of this bag is " << maxSize << std::endl;
return maxSize;
}
};
Here is another file provided by my professor called kvpairs:
#ifndef KVPAIR_H
#define KVPAIR_H
// Container for a key-value pair
// Key object must be an object for which the == operator is defined.
// For example, int and string will work since they both have == defined,
// but Int will not work since it does not have == defined.
template <typename Key, typename E>
class KVpair {
private:
Key k;
E e;
public:
// Constructors
KVpair() {}
KVpair(Key kval, E eval)
{
k = kval; e = eval;
}
KVpair(const KVpair& o) // Copy constructor
{
k = o.k; e = o.e;
}
void operator =(const KVpair& o) // Assignment operator
{
k = o.k; e = o.e;
}
bool operator==(const KVpair& o) const {
if (o.k == k) {
return true;
}
return false;
}
//The following overload is provided by Adam Morrone, Spring 2016 class.
//Thanks Adam :)
friend ostream& operator<<(ostream& os, const KVpair& o) // output print operator
{
os << "Key: " << o.k << " Value: " << o.e;
return os;
}
// Data member access functions
Key key() { return k; }
void setKey(Key ink) { k = ink; }
E value() { return e; }
};
#endif
I am expected to show the test outputs using the above templates, but I have no idea how to do this. Also, ignore the += overload. It is incorrect and I know. I am supposed to overload it to directly add a new int to the array.
I think I understand now. I could be wrong, but this is my guess.
Your bag is singly templated, but it will be holding KVpair. They said they will use KVpair with <int, string> and <string, int>.
When they talk about testing it, that means they will be instantiating it as follows:
int main() {
ABag<KVPair<int, string>> bag;
bag.addItem(KVpair(1, "hi"));
//...
}
This is what I am pretty sure they mean by "testing it with templates".
As a minor edit, I don't know what C++ version you are using but if it's very archaic, you might need to write template instantiation like ABag<KVPair<int, string> > instead of putting them together. I remember vaguely this being an issue a long time ago.

Objects Array - C++

i am having a bit of trouble here. I dont know what i am doing wrong. My bike.cpp class is fine. But i think the problem is with bike_shed class, i am having problem with the "park" and "checklegal" methods. we are asked to do something like this: " The class BikeShed with a private array of 10 default constructed Bike objects. The class should have the following public methods:
A default constructor BikeShed() as supplied by the compiler.
A function bool park( const Bike& ) which adds a bike to an available
spot and returns true. If the BikeShed is full, the function returns
false.
A function Bike remove( const string&int ) that removes and returns
the first bike with an owner of the given name. If such a bike is not
found, the function returns a bike "None".
A function bool checkLegal() that will return true if all bikes
owned by other than "None" are legal. If a bike is found illegal
print a message printing the bike.
A function void print( ) that prints all the bikes with owners
other than "None"."
here is my code:
here is bike_shed.cpp file
#include <iostream>
#include "bike_shed.h"
#include "Bike.h"
using namespace std;
void bike_shed::print(){
cout<< "Bike: " << sizeof(Bike) <<endl;
}
bool bike_shed::checkLegal() {
Bike bike1;
if(bike1.getOwner() == "None"){
return false;
}
else{
return true;
}
}
//Bike bike_shed::remove( const string&, int ) {
//
//
//}
bool bike_shed::park( const Bike& ) {
if (sizeof(Bike) > 10) {
return false;
}
}
and here is the Bike.cpp file
#include "Bike.h"
#include <iostream>
using namespace std;
void Bike::setNLight(int _light) {
d_nLight = _light;
}
void Bike::setBell(bool _bell) {
d_bell = _bell;
}
void Bike::setOwner(string _owner) {
d_owner = _owner;
}
void Bike::setReflector(bool _reflector) {
d_reflector = _reflector;
}
int Bike::getNLight() {
return d_nLight;
}
string Bike::getOwner() {
return d_owner;
}
bool Bike:: hasReflector() {
if (d_reflector == true) {
return true;
}
else {
return false;
}
}
bool Bike:: hasBell(){
if(d_bell == true) {
return true;
}
else{
return false;
}
}
bool Bike::isLegal() {
if (d_nLight >= 1 && d_reflector && d_bell) {
return true;
}
else {
return false;
}
}
void Bike::print() {
cout << "Owner: " << d_owner << " Color: " << d_color.Red << " " << d_color.Green << " " << d_color.Blue
<< " " << " Lights: " << d_nLight << " Bell: " << d_bell << " Reflector: " <<d_reflector << endl;
}
Bike::Bike(string name, Color color){
d_owner = name;
d_color = color;
}
and here is the bike_shed.h file
#include "Bike.h"
class bike_shed {
public:
bike_shed();
bool park( const Bike& );
Bike remove( const string&, int );
bool checkLegal();
void print();
public:
Bike bike[10];};
i would really appreciate if someone can help me. Thank you :)
In the following block of code,
if (sizeof(Bike) > 10) {
return false;
}
I am guessing that you are trying to make sure that you don't allow parking of more than 10 bikes in the shed.
In order to do that, you need to have a member variable in park_shed to indicate the number of bikes parked in the shed. Then, you can use:
bool bike_shed::park( const Bike& bike)
{
if ( number_of_parked_bikes < 10 )
{
bikes[number_of_parked_bikes] = bike;
++number_of_parked_bikes;
return true;
}
else
{
retun false;
}
}
Make sure to initialize number_of_parked_bikes to zero in the constructor.
The checkLegal function would be something like:
// Make it a `const` member function since it does not
// change anything in bike_shed.
bool bike_shed::checkLegal() const
{
bool isLegal = true;
for ( int i = 0; i < number_of_parked_bikes; ++i )
{
if ( bikes[i].getOwner() == "None" )
{
// No need to check whether this bike is legar or not.
}
else if (!bikes[i].isLegal() )
{
isLegal = false;
cout << "Illegal bike found.\n";
bikes[i].print();
}
}
return isLegal;
}
In method checkLegal() you may want to check whether a given Bike is valid or not before insertion, so you can write something like :
bool bike_shed::checkLegal(const Bike &bike1) {
if(bike1.getOwner() == "None"){ // or maybe bike1.isLegal()
return false;
}
else{
return true;
}
}
Also if you want to print all bikes in bike_shed you might want to write something like :
void bike_shed::print(){
for (int iBike = 0; iBike < nbBikes < iBike++)
bike[iBike].print();
}

Cref postincrementation in Map definition

So I have such definition on map class on vector, it works good except for post-incrementation, which doesn't work as it should. You can see in example that variable a should be equal to 10 (post-incremented after assignment). But it's equal to 11. I have no idea how to fix that.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
template<class T>
class Map {
class Cref {
friend class Map;
Map& m;
string key;
T value;
public:
operator double() {
return m.read(key);
};
Map::Cref & operator=(double num) {
m.write(key, num);
return *this;
};
Map::Cref & operator++(int) {
Cref c(*this);
m.increment(key, value);
return c;
}
Cref(Map& m, string a)
: m(m),
key(a) {};
};
public:
class Unitialized {};
struct Record {
string key;
T value;
};
vector<Record> data;
Map() {}
~Map() {}
bool ifexist(string k) {
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == k)
return 1;
}
return 0;
}
Cref operator[](string key) {
return Map::Cref( * this, key);
}
private:
void increment(string key, T value) {
if (ifexist(key) == 0) {
throw Unitialized();
}
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == key)
data.at(i).value += 1;
}
}
void write(string key, T value) {
if (ifexist(key) == 1) {
cout << "Element already exist" << endl;
return;
}
Record r;
r.key = key;
r.value = value;
data.push_back(r);
}
double read(string key) {
if (ifexist(key) == 0) {
throw Unitialized();
}
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == key)
return data.at(i).value;
}
return 0;
}
};
int main(int argc, char** argv) {
Map<int> m;
m["ala"] = 10;
int a = 0;
a = m["ala"]++;
cout << a << endl;
try {
cout << m["ala"] << endl;
cout << m["ola"] << endl;
} catch (Map<int>::Unitialized&) {
cout << "Unitialized element" << endl;
}
return 0;
}
Yes, I already fixed that, overloading of ++ operator should look like that :
T operator ++(int)
{
T ret = m.read(this->key);
m.increment(key, value);
return ret;
}
This fixes everything.