2D Vectors Segmentation Fault:push_back - c++

I am trying to solve a problem dealing with 2d vectors array.FunClass gets two parameters, number of sets and the lines per set.
The problem is whenever update_mytable function is being called a segmentation fault error pops up.During a quick search on stackoverflow I read that in most cases the issue for the seg-fault is because we are trying to access to a non-existed vector.But I don't think what I have the same issue here.
using std::vector;
typedef vector<mytable_entry>::iterator mytable_iter;
struct mytable_entry
{
int x_entry;
int y_entry;
};
mytable_entry new_mytable_entry(int new_ip, int new_target) {
mytable_entry new_entry;
new_entry.ip_entry = new_ip;
new_entry.target_entry = new_target;
return new_entry;
}
class FunClass : public BaseClass
{
public:
FunClass(unsigned mytable_sets, unsigned mytable_lines_per_set)
: table_sets(mytable_sets), table_assoc(mytable_lines_per_set)
{
mytable_table = vector< vector<mytable_entry> > (table_sets,vector< mytable_entry> (table_assoc));
}
~FunClass() {
/* Vectors will be decontructed automatially out of scope */
}
virtual bool predict(int x, int y) {
/* If mytable_entry exist return true, else false */
unsigned mytable_set_index = x % table_sets;
if (find_mytable_entry(mytable_table[mytable_set_index])) {
return true;
} else {
return false;
}
}
virtual void update(bool val1, bool val2, int x, int y) {
unsigned mytable_set_index = x % table_sets;
if (val1 == val2){
update_mytable_table(mytable_table[mytable_set_index],ip,target_entry,table_assoc);
}
void update_mytable(vector<mytable_entry> & mytable_set, int x, int y,unsigned table_assoc){
mytable_entry new_entry = new_mytable_entry(ip,target);
mytable_set.push_back(new_entry);
if (mytable_set.size() > table_assoc){
mytable_set.erase(mytable_set.begin());
}
}
bool find_mytable_entry(vector<mytable_entry> & mytable_set, int x) {
mytable_iter iter;
for (iter = mytable_set.begin(); iter != mytable_set.end(); iter++){
if ((*iter).ip_entry == ip) {
mytable_entry tmp_mytable_entry = (*iter);
mytable_set.erase(iter);
mytable_set.push_back(tmp_mytable_entry);
return true;
}
}
return false;
}
private:
vector< vector<mytable_entry> > mytable_table;
unsigned table_sets, table_assoc;
};
If I remove the mytable_set.push_back(new_entry); from update_mytable everything goes fine then.

Related

How to restructure this code without duplicating too much code?

class
{
public:
void func(const int val, const bool flag)
{
if(flag)
{
while(!lower.empty() && val <= lower.top())
{
// do a bunch of stuff with lower
}
}
else
{
while(!higher.empty() && val >= higher.top())
{
// do a bunch of stuff with higher, but it's the same stuff as would've done
// for lower
}
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
I'm trying to figure out a better way to write the clauses because currently, I have a lot of duplicate code in both. The only difference is one clause operates on lower and the other on higher and the <= in the first clause is changed to >= higher in the second one.
I could wrap the clause in a helper function and call it in each clause (and pass in the lower and higher as an argument), e.g.,
class
{
public:
void func(const int val, const bool flag)
{
if(flag)
{
helper(lower, comparer);
}
else
{
helper(lower, comparer);
}
}
void helper(std::stack<int> &st)
{
// do a bunch of stuff with st
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
I'm not sure if this is a good idea and if it is, I'm not sure how to get around the >= vs. <=. I'm hoping for suggestions on my design!
You can do something like the following:
class
{
public:
void func(const int val, const bool flag)
{
std::stack<int> *st;
bool (*compare)(int, int);
if (flag)
{
st = &lower;
compare = [](int a, int b){ return a <= b; };
}
else
{
st = &higher;
compare = [](int a, int b){ return a >= b; };
}
while (!st->empty() && compare(val, st->top()))
{
// do a bunch of stuff with *st
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
Alternatively, using a helper would certainly work, too:
class
{
public:
void func(const int val, const bool flag)
{
if (flag)
func_helper(lower, val, std::less_equal{});
else
func_helper(higher, val, std::greater_equal{});
}
private:
std::stack<int> lower;
std::stack<int> higher;
template<typename Comparer>
void func_helper(stack<int> &st, const int val, Comparer compare)
{
while (!st.empty() && compare(val, st.top()))
{
// do a bunch of stuff with st
}
}
}
How about something like this
class
{
public:
void func(const int val, const bool flag)
{
int sign = 1;
std::stack<int>* higher_or_lower = &higher;
if(flag)
{
higher_or_lower = &lower;
sign = -1;
}
while(!higher_or_lower->empty() && sign*val >= sign*higher_or_lower->top())
{
// do a bunch of stuff with higher_or_lower
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
The higher_or_lower covers both stacks and the sign takes care of less than vs. greater than.
Or a bit more compact:
class C
{
public:
void func(const int val, const bool flag)
{
const std::stack<int>* st[] = {&lower, &higher};
bool (*compare[])(int, int) = { [](int a, int b) { return a <= b; } , [](int a, int b) { return a >= b; } };
while (!st[flag]->empty() && compare[flag](val, st[flag]->top()))
{
// do a bunch of stuff with *st
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
};

Alternate branching strategies in Gecode

I post here to ask if there is a way to alternate different strategies of branching. Let me explain, I have an efficient branching strategy which we'll call the strategy A. The biggest problem is that the strategy A cannot be used that often. So when I cannot use the strategy A, I use another strategy, which I'll call the strategy B, which is less efficient.
The documentation says that:
Brancher order. Creating a brancher registers it with its home space. A space maintains a queue of its branchers in that the brancher that is registered first is also used first for
branching. The first brancher in the queue of branchers is referred to as the current brancher.
So, I supposed that if I post the brancher A then the brancher B, the brancher A will has priority and each time the status of A says there is no branching to do, the brancher B will be used. Seems like I was wrong because when the status of a brancher return false, it is never called again.
Here is a "minimal example":
#include <gecode/minimodel.hh>
#include <iostream>
using namespace Gecode;
using namespace std;
class MyChoice : public Choice {
public:
int pos; // Position of the variable
int val; // Value of to assign
MyChoice(const Brancher& b, int pos0, int val0)
: Choice(b,2), pos(pos0), val(val0) {}
// Report size occupied
virtual size_t size(void) const {
return sizeof(*this);
}
// Archive into e
virtual void archive(Archive& e) const {
Choice::archive(e);
e << pos << val;
}
};
class BranchA : public Brancher {
protected:
ViewArray<Int::IntView> x;
public:
BranchA(Home home, ViewArray<Int::IntView>& x0)
: Brancher(home), x(x0) {}
static void post(Home home, ViewArray<Int::IntView>& x) {
(void) new (home) BranchA(home,x);
}
virtual size_t dispose(Space& home) {
(void) Brancher::dispose(home);
return sizeof(*this);
}
BranchA(Space& home, bool share, BranchA& b)
: Brancher(home,share,b) {
x.update(home,share,b.x);
}
virtual Brancher* copy(Space& home, bool share) {
return new (home) BranchA(home,share,*this);
}
// status
virtual bool status(const Space& home) const {
for (int i=0; i<x.size(); i++)
if (!x[i].assigned())
return !i%2 && x[i].in(1);
return false;
}
// choice
virtual Choice* choice(Space& home) {
for (int i=0; true; i++)
if (!x[i].assigned())
return new MyChoice(*this,i,1);
GECODE_NEVER;
return NULL;
}
virtual Choice* choice(const Space&, Archive& e) {
int pos, val;
e >> pos >> val;
return new MyChoice(*this, pos, val);
}
// commit
virtual ExecStatus commit(Space& home,
const Choice& c,
unsigned int a) {
const MyChoice& pv = static_cast<const MyChoice&>(c);
int pos=pv.pos, val=pv.val;
if (a == 0)
return me_failed(x[pos].eq(home,val)) ? ES_FAILED : ES_OK;
else
return me_failed(x[pos].nq(home,val)) ? ES_FAILED : ES_OK;
}
};
void branchA(Home home, const IntVarArgs& x) {
if (home.failed()) return;
ViewArray<Int::IntView> y(home,x);
BranchA::post(home,y);
}
// BranchB //////////////////////////////////////////////////////
class BranchB : public Brancher {
protected:
ViewArray<Int::IntView> x;
public:
BranchB(Home home, ViewArray<Int::IntView>& x0)
: Brancher(home), x(x0) {}
static void post(Home home, ViewArray<Int::IntView>& x) {
(void) new (home) BranchB(home,x);
}
virtual size_t dispose(Space& home) {
(void) Brancher::dispose(home);
return sizeof(*this);
}
BranchB(Space& home, bool share, BranchB& b)
: Brancher(home,share,b) {
x.update(home,share,b.x);
}
virtual Brancher* copy(Space& home, bool share) {
return new (home) BranchB(home,share,*this);
}
// status
virtual bool status(const Space& home) const {
for (int i=0; i<x.size(); i++)
if (!x[i].assigned())
return i%2 && x[i].in(2);
return false;
}
// choice
virtual Choice* choice(Space& home) {
for (int i=0; true; i++)
if (!x[i].assigned())
return new MyChoice(*this,i,2);
GECODE_NEVER;
return NULL;
}
virtual Choice* choice(const Space&, Archive& e) {
int pos, val;
e >> pos >> val;
return new MyChoice(*this, pos, val);
}
// commit
virtual ExecStatus commit(Space& home,
const Choice& c,
unsigned int a) {
const MyChoice& pv = static_cast<const MyChoice&>(c);
int pos=pv.pos, val=pv.val;
if (a == 0)
return me_failed(x[pos].eq(home,val)) ? ES_FAILED : ES_OK;
else
return me_failed(x[pos].nq(home,val)) ? ES_FAILED : ES_OK;
}
};
void branchB(Home home, const IntVarArgs& x) {
if (home.failed()) return;
ViewArray<Int::IntView> y(home,x);
BranchB::post(home,y);
}
// Minimal Space ///////////////////////////////////////
class TestSpace : public Space {
protected:
IntVarArray x;
public:
TestSpace(int size)
: x(*this, size, 0, 10) {
branchA(*this, x);
branchB(*this, x);
}
TestSpace (bool share, TestSpace& s)
: Space(share, s) {
x.update(*this, share, s.x);
}
virtual Space* copy (bool share) {
return new TestSpace(share, *this);
}
void print(std::ostream& os) {
os << "x= " << x << endl;
}
};
// Minimal Main //////////////////////:
int main (int, char**) {
// create model and search engine
TestSpace* m = new TestSpace(10);
DFS<TestSpace> e(m);
delete m;
// search and print all solutions
while (TestSpace* s = e.next()) {
s->print(cout); delete s;
}
return 0;
}
In this example, the status of the brancher A return true if the next variable to assign is on an even index and if the variable can take the value of 1 (false else). And the brancher B status return true if the next variable to assign is on an odd index and if the variable can take the value of 2 (false else).
With that code I expected to get the solutions [1, 2, 1, 2, ...] and [!1, !2, !1, !2, ...] (and others combinations like [!1, 2, 1, !2, ...]) but since the branchers are disposed when their status return false, only the two first variables have been assigned.
Is there a good way to make the brancher not being disposed after its status return false (or to alternate two differents branching strategies) or should I merge the two branchers into one ?
If it may help someone, here is the solution I used.
As advised by Patrick Trentin, I unified the control by making a third brancher which is a vector of branchers. Here is the implementation I used:
The header branchAllInOne.h:
#include <gecode/minimodel.hh>
using namespace Gecode;
using namespace std;
class BranchAllInOne : public Brancher {
protected:
// Queue of brancher (may be better with ActorLink)
vector<Actor *> queue;
// Every brancher are in the brancher
BrancherGroup group;
mutable int toChoose;
class ChoiceAndID : public Choice {
public:
// Choice of the brancher used
Choice* c;
/// ID of brancher used
unsigned int id;
ChoiceAndID(const Brancher& b, Choice * c, unsigned int id);
virtual ~ChoiceAndID();
virtual size_t size(void) const ;
virtual void archive(Archive& e) const ;
};
public:
BranchAllInOne(Home home);
virtual size_t dispose(Space& home);
BranchAllInOne(Home home, bool share, BranchAllInOne& b);
virtual ~BranchAllInOne();
/**
* Check status of brancher, set toChoose value to the ID of the first
* brancher with alternative left
**/
virtual bool status(const Space&) const ;
/**
* Let the brancher of ID toChoose make the choice
*/
virtual Choice* choice(Space&);
virtual Choice* choice(const Space&, Archive& e);
/**
* Let the brancher of ID toChoose commit his choice
*/
virtual ExecStatus commit(Space& home, const Choice& _c, unsigned int a);
/// Copy brancher
virtual Actor* copy(Space& home, bool share);
/// Post brancher
static BranchAllInOne * post(Home home);
virtual void print(const Space& home,
const Choice& c,
unsigned int a,
ostream& o) const ;
void pushBrancher(Space& home, Brancher *b);
};
BranchAllInOne * branchAllInOne(Home home);
The implementation branchAllInOne.cpp:
#include "branchAllInOne.h"
static Brancher * ActorToBrancher(Actor *a);
// Choice implementation
BranchAllInOne::ChoiceAndID::ChoiceAndID(const Brancher& b, Choice * c0, unsigned int id0)
: Choice(b, c0->alternatives()),
c(c0),
id(id0){}
BranchAllInOne::ChoiceAndID::~ChoiceAndID() {
delete c;
}
size_t BranchAllInOne::ChoiceAndID::size(void) const {
return sizeof(*this) + c->size();
}
void BranchAllInOne::ChoiceAndID::archive(Archive& e) const {
Choice::archive(e);
c->archive(e);
}
BranchAllInOne::BranchAllInOne(Home home)
: Brancher(home),
toChoose(-1) {
home.notice(*this,AP_DISPOSE);
}
// brancher
BranchAllInOne * BranchAllInOne::post(Home home) {
return new (home) BranchAllInOne(home);
}
size_t BranchAllInOne::dispose(Space& home) {
home.ignore(*this, AP_DISPOSE);
size_t size = queue.size() * sizeof(Actor*);
for (unsigned int i = queue.size() ; i--;) {
size += ActorToBrancher(queue[i])->dispose(home);
}
queue.~vector();
// Making sure to kill each brancher inserted in the queue (may be useless)
group.kill(home);
(void) Brancher::dispose(home);
return sizeof(*this) + size;
}
BranchAllInOne::BranchAllInOne(Home home, bool share, BranchAllInOne& b)
: Brancher(home, share, b),
queue(b.queue.size()),
toChoose(b.toChoose){
for (unsigned int i = 0 ; i < queue.size() ; i++)
queue[i] = b.queue[i]->copy(home, share);
}
BranchAllInOne::~BranchAllInOne() {
for (unsigned int i = 0 ; i < queue.size() ; i++) {
delete queue[i];
}
queue.~vector();
}
Actor* BranchAllInOne::copy(Space& home, bool share){
return new (home) BranchAllInOne(home, share, *this);
}
// status
bool BranchAllInOne::status(const Space& s) const {
for (unsigned int i = 0 ; i < queue.size() ; i++) {
if (ActorToBrancher(queue[i])->status(s)) {
toChoose = i;
return true;
}
}
std::cout << std::endl;
return false;
}
// choice
Choice* BranchAllInOne::choice(Space& s) {
ChoiceAndID* res = new ChoiceAndID(*this,
const_cast<Choice *>(ActorToBrancher(queue[toChoose])->choice(s)),
toChoose);
toChoose = -1;
return res;
}
Choice* BranchAllInOne::choice(const Space& s, Archive& e) {
return new ChoiceAndID(*this,
const_cast<Choice *>(ActorToBrancher(queue[toChoose])->choice(s, e)),
toChoose);
}
// Perform commit for choice \a _c and alternative \a a
ExecStatus BranchAllInOne::commit(Space& home, const Choice& c, unsigned int a) {
const BranchAllInOne::ChoiceAndID& ch = static_cast<const BranchAllInOne::ChoiceAndID&>(c);
return ActorToBrancher(queue[ch.id])->commit(home, const_cast<Choice&>(*ch.c), a);
}
void BranchAllInOne::print(const Space& home,
const Choice& c,
unsigned int a,
ostream& o) const {
const BranchAllInOne::ChoiceAndID& ch = static_cast<const BranchAllInOne::ChoiceAndID&>(c);
o << ch.id << ": ";
ActorToBrancher(queue[ch.id])->print(home, *(ch.c), a, o);
}
void BranchAllInOne::pushBrancher(Space &home, Brancher *b) {
queue.push_back(b);
group.move(home, *b);
}
static Brancher * ActorToBrancher(Actor *a) {
return dynamic_cast<Brancher *>(a);
}
// end of BranchAllInOne implementation
BranchAllInOne* branchAllInOne(Home home) {
if (home.failed()) return NULL;
return BranchAllInOne::post(home);
}
I've made some modifications to get a pointer to branchers I want to put in the vector (that include the post function of each branchers):
brancherA example:
BranchA * BranchA::post(Home home, ViewArray<Int::IntView>& x) {
return new (home) BranchA(home,x);
}
BranchA * branchA(Home home, const IntVarArgs& x) {
if (home.failed()) return NULL;
ViewArray<Int::IntView> y(home,x);
return BranchA::post(home,y);
}
The space has also been modified:
TestSpace::TestSpace(int size)
: x(*this, size, 0, 10) {
BranchAllInOne * b = branchAllInOne(*this);
b->pushBrancher(*this, branchA(*this, x));
b->pushBrancher(*this, branchB(*this, x));
}
I tested it with and without Gist and only got a memory leak of a pointer for each brancher put in the vector (here only two). A small problem remain is that branchers put in the vector are also scheduled after the third brancher stoped (but their status return false).

Function returning function pointer from table as a parameter

I have been reading for a while, but today I can't figure someting out and find a solution.
How to return a function pointer from a function table as parameter? All similair solutions don't work for this one and end up not compiling.
I have tried a lot of methods but the compiler always returns with errors like:
function returning function is not allowed solution (when using typedef void (*func)();)
As NO parameters have to be passed into the final routine it should be possible.
My simplified example:
void PrintOne(void) { printf("One")};
void PrintTwo(void) { printf("Two")};
struct ScanListStruct
{
int Value;
void (*Routine)(void);
}
const ScanListStruct DoList[] =
{
{1, PrintOne},
{2, PrintTwo}
}
bool GetRoutine(void *Ptr, int Nr)
{
for (int x =0; x<=1; x++)
{
if (DoList[x].Value = Nr)
{
Ptr = DoList[(x)].Routine;
//((*DoList[(x)].Routine)()); // Original Working and executing version!
return true;
}
}
return false;
}
void main(void)
{
int y = 1;
void (*RoutineInMain)(); // Define
if (GetRoutine( RoutineInMain, y) == true) // get the address
{
RoutineInMain(); // Execute the function
}
}
There a few things wrong with the code;
Syntax errors (missing ; etc.)
main must return int
GetRoutine should accept the function pointer by reference, not just a void* pointer to anything
if condition should contain an equality test, not an assignment
As follows, works as expected;
void PrintOne(void) { printf("One"); };
void PrintTwo(void) { printf("Two"); };
struct ScanListStruct
{
int Value;
void (*Routine)(void);
};
const ScanListStruct DoList[] =
{
{1, &PrintOne},
{2, &PrintTwo}
};
bool GetRoutine(void (*&Ptr)(), int Nr)
{
for (int x =0; x<=1; x++)
{
if (DoList[x].Value == Nr)
{
Ptr = *DoList[(x)].Routine;
//((*DoList[(x)].Routine)()); // Original Working and executing version!
return true;
}
}
return false;
}
int main(void)
{
int y = 1;
void (*RoutineInMain)(); // Define
if (GetRoutine( RoutineInMain, y) == true) // get the address
{
RoutineInMain(); // Execute the function
}
}
Prints One.
You have lots of errors in your code. Like here you put the comas at the wrong place:
void PrintOne(void) { printf("One")};
void PrintTwo(void) { printf("Two")};
It should be
void PrintOne(void) { printf("One");}
void PrintTwo(void) { printf("Two");}
And here you are using the wrong operator, = instead of ==.
if (DoList[x].Value = Nr)
When the argument Ptr is a pointer, and that is passed by value, so the value assigned in the function will not be available when the function returns.
This is how your code should be:
void PrintOne(void) { printf("One"); }
void PrintTwo(void) { printf("Two"); }
typedef void(*prototype)();
struct ScanListStruct
{
int Value;
prototype Routine;
};
const ScanListStruct DoList[] =
{
{ 1, PrintOne },
{ 2, PrintTwo }
};
bool GetRoutine(prototype &Ptr, int Nr)
{
for (int x = 0; x <= 1; x++)
{
if (DoList[x].Value == Nr)
{
Ptr = DoList[(x)].Routine;
return true;
}
}
return false;
}
int main()
{
int y = 1;
prototype RoutineInMain; // Define
if (GetRoutine(RoutineInMain, y) == true) // get the address
{
RoutineInMain(); // Execute the function
}
return 0;
}

strange segfault using template as parameter

I have a sorted list, which takes a Comparator as parameter. In a unit test I tried to use two different comparators.
The strange thing is, using the StringReverseComparator with the two if-statements disabled (commented out), all works well and valgrind does not claim any error.
template<typename T> class Comparator {
public:
virtual int compare(const T * left, const T * right) = 0;
};
class StringReverseComparator : public Comparator<String> {
public:
int compare(const String *left, const String *right) {
int rv = strcasecmp((const char *)*left, (const char *)*right);
if (rv < 0) return 10;
if (rv > 0) return -10;
return rv;
}
};
class StringComparator : public Comparator<String> {
public:
int compare(const String *left, const String *right) {
return strcasecmp(left->operator const char*(), right->operator const char*());
}
};
As soon as I enable both if-statements, I get a segfault from sort method.
Sort method is the standard qsort by sedgewick.
const char * is an operator from String class to access the character array.
First I thought, that changing the comparator might cause troubles, so I created a new instance of sorted list. But that traps too as soon as I have the two if-statements enabled.
So what's wrong with the compare method?
//edit:
Ok, first the sort code (taken from sedgewick):
template<typename T> class SortedList {
public:
// rest omitted
protected:
void sort() { qsort(0, _size - 1); }
void qsort(int left, int right) {
if (right > left) {
const T *v = _elements[right], *tmp;
int i = left-1;
int j = right;
for (;;) {
while (_comparator->compare(_elements[++i], v) < 0) ;
while (_comparator->compare(_elements[--j], v) > 0) ;
if (i >= j) break;
tmp = _elements[i];
_elements[i] = _elements[j];
_elements[j] = tmp;
}
tmp = _elements[i];
_elements[i] = _elements[right];
_elements[right] = tmp;
qsort(left, i-1);
qsort(i+1, right);
}
}
private:
int _size;
const T **_elements;
Comparator<T> *_comparator;
};
... and here the operator char *.
by the way: String class passed all unit tests and was ok with valgrind too.
class String {
public:
// rest omitted
operator const char * () const { return _s; }
const char * operator * () const { return _s; }
private:
char *_s;
};
about usage of strcasecmp: my first attempt was:
return strcasecmp( ... ) * (-1);
using the same parameters as in StringComparator. When that failed, I tried anything I could imagine about, including the if-statements and different call syntax of operator char *.
strcasecmp does not return just -1, 0, 1 - as mentioned in many tutorials. The return value differs in size and sign and after -1, 0, 1 failed to, I tried using 10. The value has no significance, could be 815 or 42, what ever.
// edith 2
Thanks you all for your attention!
I solved it myself. The point is, the qsort algo was not safe enuf :(
The following sort code works fine (with any kind of comparator):
void qsort(int left, int right) {
if (right > left) {
const T *v = _elements[right], *tmp;
int i = left-1;
int j = right;
for (;;) {
while (++i < _size && _comparator->compare(_elements[i], v) < 0) ;
while (--j > 0 && _comparator->compare(_elements[j], v) > 0) ;
if (i >= j) break;
tmp = _elements[i];
_elements[i] = _elements[j];
_elements[j] = tmp;
}
tmp = _elements[i];
_elements[i] = _elements[right];
_elements[right] = tmp;
qsort(left, i-1);
qsort(i+1, right);
}
}
Thanks.

error C2512 in a struct with no explicit constructor

I am receiving error C2512: 'LoadingWorldlet' : no appropriate default constructor available, when I try to compile this file. There is no explicit constructor, so I can not think of a reason for me to be recieving this error.
struct Worldlet {
int x, z;
glm::mat4 worldletMatrix;
std::vector<Voxel> blocks;
};
struct LoadingWorldlet {
int x, z;
std::future<Worldlet> &result;
};
class World {
public:
World();
~World();
void Init();
void InitRenderable();
void UpdateWorldletList(int x, int z);
void Render(Shader* worldShader, Camera *mainPov);
static Worldlet LoadWorldlet(int x, int z, std::ifstream &file);
private:
std::vector<Worldlet> worldlets;
std::vector<LoadingWorldlet> loadingWorldlets;
std::vector<std::string> loadingTitles;
std::vector<int> toRemove;
Renderable cube;
std::string worldName, prefix;
static const float CUBE_SIZE;
static const int LOADLIMIT = 1;
int GetLoadRadius(int r = 0) {
static int i = r;
return i;
}
};
This is the only function in which LoadingWorldlet is used:
void World::UpdateWorldletList(int x, int z) {
static int previousX, previousZ;
for(int index: toRemove) {
worldlets.erase(worldlets.begin() + index);
}
toRemove.clear();
int loaded = 0;
std::vector<int> clearList;
for(auto &loading: loadingWorldlets) {
if(loaded >= LOADLIMIT) break;
worldlets.push_back(loading.result.get());
clearList.push_back(loaded);
loaded++;
}
for(int i: clearList)
loadingWorldlets.erase(loadingWorldlets.begin()+i);
if(previousX != x && previousZ != z) {
int i = 0;
for(auto worldlet: worldlets) {
if(pow(worldlet.x - x, 2) + pow(worldlet.z - z, 2) > GetLoadRadius()) {
toRemove.push_back(i);
}
i++;
}
for(int recX = -GetLoadRadius(); recX < GetLoadRadius(); recX++) {
for(int recZ = -GetLoadRadius(); recZ < GetLoadRadius(); recZ++) {
bool cont = false;
for(auto worldlet: worldlets) {
if (worldlet.x == recX && worldlet.z == recZ) {
cont = true;
break;
}
}
for(auto loading: loadingWorldlets) {
if (loading.x == recX && loading.z == recZ) {
cont = true;
break;
}
}
if(cont || pow(recX - x, 2) + pow(recZ - z, 2) > GetLoadRadius())
continue;
std::ifstream file("./worlds/" + worldName + "/" + prefix + std::to_string(recX) + "X" + std::to_string(recZ) + "Z.json");
if (!file)
continue;
LoadingWorldlet loading;
loading.x = recX;
loading.z = recZ;
loading.result = std::async(LoadWorldlet, recX, recZ, file);
loadingWorldlets.push_back(loading);
}
}
}
}
I have tried adding a default constructor, but then I receive an error about a missing = operator. Doesn't the compiler automatically add in these things? How can I fix the error? If it is important, I am using Visual Studio 2013 preview.
Looking over the code, you'll need to a way to instantiate your reference to std::future<Worldlet> &result;
Typically, this is done through a constructor.
struct LoadingWorldlet
{
LoadingWorldlet( std::future<Worldlet> & inWorldlet ):
result( inWorldlet ) {}
int x, z;
std::future<Worldlet> &result;
};
Otherwise, you could simply not make the data member a reference ( this assumes that other data members don't also have mandatory constructors):
std::future<Worldlet> result;