I would like to write a class that stores recursively the same class in a map.
I have the following source codes:
/* A.hpp */
#include <iostream>
#include <string>
#include <map>
class A
{
private:
int a;
std::map<int, A> data;
bool finishCycle;
public:
A(const int& input ) : a(input), finishCycle(false)
{
func1();
}
void func1();
};
/* A.cpp */
void A::func1()
{
A tmp(*this);
while(!finishCycle)
{
a--;
if (a == 0)
finishCycle=true;
else
func1();
}
data.emplace(tmp.a, tmp);
}
/* main.cpp*/
#include "A.hpp"
int main(int argCount, char *args[])
{
A myObj1 (3);
std::cout << "tst" << std::endl;
return 0;
}
This is putting all the entries in the main map. I would like to have it in a nested sequence:
first entry: <1, A>
inside first entry: <2,A>
inside inside first entry <3,A>
How can I change the script to do this? The nested loops still make me confused.
Maybe this is what you want?
#include <iostream>
#include <map>
class A
{
private:
std::map<int, A> data;
public:
A(int n, int i = 0) {
if (n == i) {
return;
}
data.emplace( i+1, A(n, i + 1) );
}
void test() {
if (!data.empty()) {
std::cout << data.begin()->first << "\n";
data.begin()->second.test();
}
}
};
int main()
{
A a(4);
a.test();
}
I came up with:
#include <iostream>
#include <map>
class A
{
private:
int a;
std::map<int, A> data;
bool finishCycle;
public:
A(const int& input ):a(input), finishCycle(false)
{
func1(*this);
}
void func1(A& tmp);
};
void A::func1(A& tmp)
{
A tmp2(tmp);
tmp2.a--;
while(!finishCycle)
{
if (tmp2.a == 0)
{
(*this).finishCycle=true;
}
else
{
func1(tmp2);
}
}
tmp.data.emplace(tmp2.a, tmp2);
}
int main(int argCount, char *args[])
{
A myObj1 (4);
std::cout << "tst" << std::endl;
return 0;
}
Related
Error
e/c++/v1/algorithm:642:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/utility:321:9: error:
field type 'Space' is an abstract class
_T2 second;
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/map:624:16: note:
Question
How can I define a std::vector of type Space which is an abstract class and then fill this vector with instances of the derived classes Empty, Snake, Ladder.
Context
I know abstract classes in C++ can not be instantiated. Instead I've read in several posts on this and other sites that you can create a collection of an abstract type if it the type is defined as a star * pointer or any of the <memory> managed pointer data types like std::unqiue_ptr<T>. I've tried to used shared_ptr<Space> in my case, but still unable to define the collection properly. I am compiled my code using g++ -std=c++17 main.cpp && ./a.out.
Code
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <map>
#include <memory>
#include <typeinfo>
#include <queue>
#include <string>
#include <vector>
class Player
{
private:
int m_current_space = 1;
public:
Player() {}
void role_dice() {
m_current_space += floor( (rand()%10 + 1) / 3 );
}
int const get_current_space() {
return m_current_space;
}
void set_current_space(int current_space) {
m_current_space = current_space;
}
};
class Space
{
protected:
int m_id;
std::vector<Space> m_paths;
public:
Space() {} // requied to use [] operator in map
Space(int id) : m_id(id) {}
void add_path(Space& s) {
m_paths.push_back(s);
}
int get_id() {
return m_id;
}
virtual std::string class_type() = 0;
};
class Empty : public Space
{
public:
Empty(int id) : Space(id) {}
std::string class_type() {
return "Empty";
}
};
class Ladder : public Space
{
public:
Ladder(int id) : Space(id) {}
virtual void event(Player& p) {
p.set_current_space(1);
}
std::string class_type() {
return "Ladder";
}
};
class Snake : public Space
{
public:
Snake(int id) : Space(id) {}
virtual void event(Player& p) {
p.set_current_space(4);
}
std::string class_type() {
return "Snake";
}
};
class Board
{
private:
std::map<int, Space> m_board;
public:
void add_space(Space& s) {
m_board[s.get_id()] = s;
}
void draw_board() {
int i = 1;
for(auto const& [space_key, space] : m_board) {
if(i%3 == 0) {
std::cout << "○\n";
}
else if(typeid(space) == typeid(Snake)) {
std::cout << "○-";
}
else {
std::cout << "○ ";
}
++i;
}
}
void update_player_on_board(int position) {
int i = 1;
for(auto const& [space_key, space] : m_board) {
if(i%3 == 0) {
if (space_key == position) {
std::cout << "●\n";
}
else {
std::cout << "○\n";
}
}
else if(typeid(space) == typeid(Snake)) {
std::cout << "○-";
}
else {
if (space_key == position) {
std::cout << "● ";
}
else {
std::cout << "○ ";
}
}
++i;
}
}
const std::map<int, Space> get_board() {
return m_board;
}
friend std::ostream &operator<<(std::ostream& os, const Board& b) {
return os;
}
};
class GameStateManager
{
private:
std::string m_state = "game over";
bool m_playing = false;
public:
std::string const get_state() {
return m_state;
}
void set_state(std::string state) {
m_state = state;
}
};
int main()
{
std::cout << "Welcome to Bowser's 9 board game\n";
std::cout << "Start? y(yes) n(no)\n";
GameStateManager game_manager;
game_manager.set_state("playing");
auto space1 = std::make_shared<Space>(1);
auto space2 = std::make_shared<Space>(2);
auto space3 = std::make_shared<Space>(3);
auto space4 = std::make_shared<Space>(4);
auto space5 = std::make_shared<Space>(5);
auto space6 = std::make_shared<Space>(6);
auto space7 = std::make_shared<Space>(7);
auto space8 = std::make_shared<Space>(8);
auto space9 = std::make_shared<Space>(9);
std::vector<std::shared_ptr<Space>> v {
space1, space2, space3,
space4, space5, space6,
space7, space8, space9
};
Board bowsers_bigbad_laddersnake;
for(int i = 0; i < 10; ++i) {
bowsers_bigbad_laddersnake.add_space(*(v[i]));
}
bowsers_bigbad_laddersnake.draw_board();
Player mario;
int turn = 0;
while(game_manager.get_state() == "playing") {
std::cin.get();
std::cout << "-- Turn " << ++turn << " --" << '\n';
mario.role_dice();
bowsers_bigbad_laddersnake.update_player_on_board(mario.get_current_space());
if (mario.get_current_space() >= 9) {
game_manager.set_state("game over");
}
}
std::cout << "Thanks a so much for to playing!\nPress any key to continue . . .\n";
std::cin.get();
return 0;
}
You seem to have removed a lot of code to get into details here.
Have a Space pointer (smart or raw). Instantiate the specific space that you want, point to it with your pointer of type Space. Example std::shared_ptr<Space> pointerToSpace = std::make_shared<Snake> ("I'm a snake"); Now, without loss of generality, you can print the contents (of concrete type) with just the pointer to the space pointerToSpace->class_type(). Yes, you can have a collection of shared_ptrs in a container.
I have the following code:
#include <memory>
#include <vector>
#include <iostream>
class MarchingEvent
{
public:
MarchingEvent() {}
};
class DerivedEvent : public MarchingEvent
{
public:
DerivedEvent() {}
};
std::shared_ptr<MarchingEvent> function1()
{
return std::make_shared<DerivedEvent>();
}
std::shared_ptr<MarchingEvent> function2()
{
std::shared_ptr<MarchingEvent> event = function1();
if (event)
return event; // This line crashes...
return std::shared_ptr<MarchingEvent>();
}
int main()
{
std::shared_ptr<MarchingEvent> event = function2();
std::cout << "hello";
return 0;
}
When running function2() I get a crash at line return event;, the crash is a SIGABRT and I can trace back to std file shared_ptr_base.h in the context of:
// Counted ptr with no deleter or allocator support
template<typename _Ptr, _Lock_policy _Lp>
class _Sp_counted_ptr final : public _Sp_counted_base<_Lp>
{
public:
explicit
_Sp_counted_ptr(_Ptr __p)
: _M_ptr(__p) { }
virtual void
_M_dispose() noexcept
{ delete _M_ptr; }
Do you have any idea of what I am doing wrong?
Create a simple MCVE. It will prove that either:
a) your implementation has a bug (extremely unlikely), or
b) you have a bug or UB somewhere else (extremely likely)
example MCVE:
#include <memory>
#include <vector>
#include <iostream>
class MarchingEvent
{
};
class DerivedEvent : public MarchingEvent
{
};
std::shared_ptr<MarchingEvent> function1()
{
return std::make_shared<DerivedEvent>();
}
std::shared_ptr<MarchingEvent> function2()
{
std::shared_ptr<MarchingEvent> event = function1();
if (event)
return event; // This line crashes...
return std::shared_ptr<MarchingEvent>();
}
int main()
{
for (int i = 0 ; i < 10 ; ++i)
{
std::vector<std::shared_ptr<MarchingEvent>> v(10000);
for(int j = 0 ; j < 10000 ; ++j)
{
v[j] = function2();
}
}
std::cout << "done\n";
}
strong evidence for my claim: http://coliru.stacked-crooked.com/a/1b554b334212a0ea
I created the following class
#include "cliques.h"
#include "vector"
#include <iostream>
using namespace std;
cliques::cliques(){
}
cliques::cliques(int i) {
clique.push_back(i);
clique_prob = 1;
mclique_prob = 1;
}
cliques::cliques(const cliques& orig) {
}
cliques::~cliques() {
}
void cliques::addvertex(int i) {
clique.push_back(i);
}
double cliques::getclique_prob() const {
return clique_prob;
}
double cliques::getMaxclique_prob() const {
return mclique_prob;
}
void cliques::showVertices() {
for (vector<int>::const_iterator i = clique.begin(); i !=clique.end(); ++i)
cout << *i << ' ';
cout << endl;
}
vector<int> cliques::returnVector() {
return clique;
}
void cliques::setclique_prob(double i) {
clique_prob = i;
}
void cliques::setMaxclique_prob(double i) {
mclique_prob = i;
}
Here's the header file
#include "vector"
#ifndef CLIQUES_H
#define CLIQUES_H
class cliques {
public:
void addvertex(int i);
cliques();
cliques(int i);
cliques(const cliques& orig);
virtual ~cliques();
double getclique_prob() const;
double getMaxclique_prob() const;
void showVertices();
std::vector<int> returnVector();
void setclique_prob(double i);
void setMaxclique_prob(double i);
private:
float clique_prob;
float mclique_prob;
std::vector <int> clique;
};
#endif /* CLIQUES_H */
I want to create a vector of these objects in order to implement a heap
int main(int argc, char** argv) {
cliques temp(1);
cliques temp1(2);
temp.setclique_prob(0.32);
temp.setclique_prob(0.852);
temp.showVertices();
temp1.showVertices();
vector <cliques> max_heap;
max_heap.push_back(temp);
max_heap.push_back(temp1);
double x =max_heap.front().getclique_prob();
cout<<"prob "<<x<<endl;
cliques y = max_heap.front();
y.showVertices();
//make_heap (max_heap.begin(),max_heap.end(),max_iterator());
//sort_heap (max_heap.begin(),max_heap.end(),max_iterator());
return 0;
}
For reasons unknown to me none of my class functions work properly after i create my vector, meaning that while the following function works as intended
temp.showVertices()
the next one doesn't,
y.showVertices()
You miss implementation for
cliques::cliques(const cliques& orig) {
}
STL vector uses copy constructor inside when you add values to it. As your cliques class does not allocate any memory, you can just remove the copy constructor from the code and compiler will generate one for you.
http://ideone.com/1ohrsO
The push_back called inside the constructor of static_constructor, is not reflected. Why?
#include <iostream>
#include <vector>
#include<memory>
#include<string>
using namespace std;
class has_static_constructor
{
public:
friend class static_constructor;
static vector<int> v;
class static_constructor
{
public:
vector<int> * upt; //&v;
static_constructor()
{
cout<<"inside static_constructor";
upt = &has_static_constructor::v;
has_static_constructor::v.push_back(1);
has_static_constructor::v.push_back(20);
}
} ;
static std::unique_ptr<has_static_constructor::static_constructor> upt ;
};
unique_ptr<has_static_constructor::static_constructor> has_static_constructor::upt(new has_static_constructor::static_constructor());
vector< int > has_static_constructor::v(2,100);
int main() {
// your code goes here
for (std::vector<int>::const_iterator i = has_static_constructor::v.begin(); i != has_static_constructor::v.end(); ++i)
{ std::cout << *i << ' ';
cout<<"\n I was here\n";
}
return 0;
}
Output:
inside static_constructor100
I was here
100
I was here
static_constructor() is called before has_static_constructor::v initialization.
Move
unique_ptr<has_static_constructor::static_constructor> has_static_constructor::upt(new has_static_constructor::static_constructor());
after
vector< int > has_static_constructor::v(2,100);
to have expected behaviour.
But better avoid those global entirely.
You might want to have a look at this way of ordering the code. It removes all initialisation-order dependencies, and in my view neatly separates the public interface from the internal implementation of the static data.
#include <iostream>
#include <vector>
class has_static_constructor
{
// note - all private
struct static_data {
static_data()
: _v(2, 100)
{
_v.push_back(1);
_v.push_back(20);
}
std::vector<int> _v;
};
static static_data& statics() {
static static_data sd;
return sd;
}
// public interface
public:
static std::vector<int>& v() { return statics()._v; }
};
auto main() -> int
{
for (const auto& i : has_static_constructor::v())
{
std::cout << i << std::endl;
}
return 0;
}
expected output:
100
100
1
20
I have a class like this:
class SelectorFactory
{
public:
static std::map<std::string,int> _creator;
static void registerCreator(std::string& name,int value)
{
//static std::map<std::string,int> _creator;
if(_creator.end() != _creator.find(name))
{
std::cout << "Selector already registered \n";
}
else
{
std::cout << "Entering " <<name<<" in register: \n";
_creator[name]=value;
}
}
static int createSelector(std::string selectorName)
{
//static std::map<std::string,int> _creator;
std::map< std::string , int >::iterator mapIter=_creator.find(selectorName);
if(mapIter==_creator.end())
{
std::cout<<selectorName<<" Not found in the Map \n" ;
return 0;
}
else
{
int selector= mapIter->second;
return selector;
}
}
};
If I uncomment the commented lines above, code is getting compiled but it's not returning any value from createSelector function which is quite obvious.But if I keep them commented, I am getting error as "_creator was not declared in this scope" inside both the functions.
What should I do to rectify this issue.
In order to have -creator instantiated, you must provide a definition for it. Currently, you have only a declaration.
class SelectorFactory
{
static std::map<std::string,Int> _creator;
};
std::map<std::string,Int> SelectorFactory::_creator;
SelectorFactory.h :
#ifndef __SELECTOR_FACTORY__H__
#define __SELECTOR_FACTORY__H__
#include <string>
#include <map>
class SelectorFactory
{
public:
static void registerCreator(std::string& name,int value);
static int createSelector(std::string selectorName);
private: // !!!!!!!!! NOT PUBLIC!!! >:(
static std::map<std::string,int> _creator;
};
#endif // __SELECTOR_FACTORY__H__
SelectorFactory.cpp :
#include "SelectorFactory.h"
#include <iostream>
std::map<std::string,int> SelectorFactory::_creator;
void SelectorFactory::registerCreator(std::string& name,int value)
{
if(_creator.end() != _creator.find(name))
{
std::cout << "Selector already registered \n";
}
else
{
std::cout << "Entering " <<name<<" in register: \n";
_creator[name]=value;
}
}
int SelectorFactory::createSelector(std::string selectorName)
{
std::map< std::string , int >::iterator mapIter=_creator.find(selectorName);
if(mapIter==_creator.end())
{
std::cout<<selectorName<<" Not found in the Map \n" ;
return 0;
}
else
{
int selector= mapIter->second;
return selector;
}
}