What I'm trying to do: order elements in the set by elem->value, but still recognize that they're distinct elements based on the memory address they're pointing to.
#include <iostream>
#include <set>
using namespace std;
struct Node {
int value;
Node(int v) : value(v) {}
};
int main()
{
Node* a = new Node(10);
Node* b = new Node(10);
Node* c = new Node(20);
if (a == b) {
cout << "a == b" << endl;
}
if (a == c) {
cout << "a == c" << endl;
}
auto comparator = [](Node* lhs, Node* rhs) {
return lhs->value < rhs->value;
};
set<Node*, decltype(comparator)> s(comparator);
s.insert(a);
s.insert(b);
s.insert(c);
cout << "after inserts, s.size() = " << s.size() << endl;
s.erase(a);
cout << "after erase, s.size() = " << s.size() << endl;
delete(a);
delete(b);
delete(c);
return 0;
}
Since a != b, I expect to get:
after inserts, s.size() = 3
after erase, s.size() = 2
But instead, I get:
after inserts, s.size() = 2
after erase, s.size() = 1
With lhs->value <= rhs->value, I get:
after inserts, s.size() = 3
after erase, s.size() = 3
With multiset, I get:
after inserts, s.size() = 3
after erase, s.size() = 1
You should use the memory address for tie-break.
Example:
auto comparator = [](Node* lhs, Node* rhs) {
return lhs->value < rhs->value ||
(lhs->value == rhs->value && lhs < rhs);
};
Related
Is it possible in C++ to split a flat vector (or C style array) into multiple vectors of equal size without copying any of its containing data? That is, disassembling the original vector by moving its content to a new vector, which invalidates the original vector. The following code example should illustrate this:
#include <cassert>
#include <vector>
void f(int* v) {
for (int i = 0; i < 100; i++) {
v[i] = i;
}
}
/**
* Split v into n vectors of equal size without copy its data (assert v.size() % n == 0)
*/
std::vector<std::vector<int>> g(std::vector<int> v, int n) {
std::vector<std::vector<int>> vs(n);
int vec_size = v.size() / n;
for (int i = 0; i < n; i++) {
vs[i].assign(v.begin() + i * vec_size, v.begin() + (i + 1) * vec_size); // copies?
// how to let vs[i] point to v.begin() + i * vec_size?
}
return vs;
}
int main() {
std::vector<int> v(100);
f(v.data());
std::vector<std::vector<int>> vs = g(std::move(v), 10);
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
assert(vs[i][j] == i * 10 + j);
}
}
return 0;
}
Yes, in my opinion this is possible. Moving the elements, but not copying the elements.
C++ offers std::make_move_iterator. Please read here about that.
To check that, I created a small class to output, to see, if we copy or move something.
So, if your data can "move", then it will work, otherwise of course a copy will be made. With the following we see the result.
struct Test {
int data{};
Test(int d) : data(d) { std::cout << "Construct and init\n"; }
Test() { std::cout << "Default construct\n"; };
~Test() { std::cout << "Destruct\n"; };
Test(const Test& other) { std::cout << "Construct\n"; data = other.data; }
Test(const Test&& other) noexcept { std::cout << "Move Construct\n"; data = other.data; }
Test& operator =(const Test& other) noexcept { std::cout << "Assign\n"; data = other.data; return *this; }
Test& operator =(const Test&& other) noexcept { std::cout << "Move Assign\n"; data = other.data; return *this; }
};
We will additionally add a small function, which calculates the offsets of the chunks that will be moved.
And then, we can come up with a small function to implement that.
#include <iostream>
#include <vector>
#include <numeric>
#include <iterator>
#include <iomanip>
// Calculate start and end index for all chunks
std::vector<std::pair<size_t, size_t>> calculatePairs(const size_t low, const size_t high, const size_t numberOfGroups) {
// Here we will store the resulting pairs with start and end values
std::vector<std::pair<size_t, size_t>> pairs{};
// Calculate chung size and remainder
const size_t delta = high - low;
const size_t chunk = delta / numberOfGroups;
size_t remainder = delta % numberOfGroups;
// Calculate the chunks start and end addresses for all chunks
size_t startIndex{}, endIndex{};
for (size_t i = 0; i < numberOfGroups; ++i) {
// Calculate end address and distribute remainder equally
endIndex = startIndex + chunk + (remainder ? 1 : 0);
// Store a new pair of start and end indices
pairs.emplace_back(startIndex, endIndex);
// Next start index
startIndex = endIndex;
// We now consumed 1 remainder
if (remainder) --remainder;
}
//--pairs.back().second;
return pairs;
}
struct Test {
int data{};
Test(int d) : data(d) { std::cout << "Construct and init\n"; }
Test() { std::cout << "Default construct\n"; };
~Test() { std::cout << "Destruct\n"; };
Test(const Test& other) { std::cout << "Construct\n"; data = other.data; }
Test(const Test&& other) noexcept { std::cout << "Move Construct\n"; data = other.data; }
Test& operator =(const Test& other) noexcept { std::cout << "Assign\n"; data = other.data; return *this; }
Test& operator =(const Test&& other) noexcept { std::cout << "Move Assign\n"; data = other.data; return *this; }
};
std::vector<std::vector<Test>> split(std::vector<Test>& v, unsigned int n) {
std::vector<std::vector<Test>> result{};
if (v.size() > n) {
result.resize(n);
std::vector<std::pair<size_t, size_t>> offset = calculatePairs(0u, v.size(), n);
for (size_t i{}; i < n; ++i) {
result[i].insert(result[i].end(), std::make_move_iterator(v.begin() + offset[i].first),
std::make_move_iterator(v.begin() + offset[i].second));
}
}
return result;
}
constexpr size_t NumberOfElements = 30u;
constexpr unsigned int NumberOfGroups = 3;
static_assert (NumberOfElements >= NumberOfGroups, "Number of elements must be greater/equal then number of elements\n");
int main() {
std::cout << "\n\n\nCreate vector with " << NumberOfElements << " elements\n\n";
std::vector<Test> v1(NumberOfElements);
std::cout << "\n\n\nFill vector with std::iota\n\n";
std::iota(v1.begin(), v1.end(), 1);
std::cout << "\n\n\nSplit in " << NumberOfGroups<< "\n\n";
std::vector<std::vector<Test>> s = split(v1, NumberOfGroups);
std::cout << "\n\n\nOutput\n\n";
for (const std::vector<Test>& vt : s) {
for (const Test& d : vt) std::cout << std::setw(3) << d.data << ' ';
std::cout << "\n\n";
}
}
But my strong guess is that you want to splice the data. The underlying elements fo the std::vector which you can get with the data() function.
You can access the data easily with pointer arithmetic on data().
But if you want to have the data in a new container, then this is difficult with a std::vector. It can for example be done with a std::list that has a splice function and does, what you want.
Or, you need to implement your own dynamic array and implement a splice function . . .
Checksum:
;23M#eTo1?:B#r7C8#wtJ'Z'..uIvLT.j;bld$Bvgjd.qm=8;B/`dHM%D#wyv:\5YI:WVGwJL00%IsKQ9O+&#g,/gzkPg^cg::LX?6dL3;Fs3GOOAmQmCIW?&skWxZXsElyn6S3#fi:0DSKJ/A^r#*'k#a#e8!XDpjAUtu?K5iu+e=P"M7a2BWdFdA.5NP:Y"l,,h+Y/PxhVfP/m0ceS=Nxol2vOZwM2+!H\^a=douX%fhqcr4'0eXiEZeKvTf0^%CTNY^WB6fc#IpK^GQgxTXQo0ikr0+/OxXlc1B$5jc1r,GQj+fwEdoCPrz6,j:SO6L3QU#7lT:f#Y^V!Au\P'a5amR$NCU?\WspBOuy#RH3tJimka#rdyNN56.$;DtRCHN*YeWlrG=',XNSrzEK:Cw;#A%.#/:c,a2W24IIIdecc7O"EnKQn;nXmUemX4kclDsYci+izmr#vlGAQ.w2!cuf;6n2UvJM,CeSyRj1,:2\9#i8GLwtux!uEHUp7X*5SC%nld956CHsy&/n73/90cRP'Me"1PW+##FH8mH4Rf^o=ZP/Rm\X&1syUdUh+.N/jtoO:,OBBAmq,jW69Fu%jJukBa$g4hIrIPcxx17i;XU,FCbQGd8v*AyKGSML\JN#jte*F";Zh7fqhvCXobE&SapX90r"Z$.CN,1R^aj.=5L6^tUB2UPJH^eb'*B!v5=D.9PFI#Pt*KjK+yS*tV6f.5kgPOzBE$uK0MA/\l9U"63LUR6k3#'cub?u&xILMXP%#:lx2TbKhFOjBpMN!+%F16jrgv&AoFhuf%P!==8?x,NsSd%hVo"BJhVv3rjrhvM"WLE3%y#N7g37Re^XiS9lpyKA9E7ow6U=I"tlv",&#+fZoIR4KM58!NTm978wCI?9wo.ocS!9i5k#ler47J.G0yXjZVSdr=G"uRodC06k\V%8;oUwV&z!W5:+ZvE:nyO#+lO+Hn0&tnH&^tNC?'PmERxs/B+KW4O6&oWDED9?MqxmYgVKoT.a%iw
I'm trying to figure out some points on using unordered_map for custom class. Below are the codes I use to take exercise where I define a simple class Line. I'm confused that why the insertion of Line2 in main() does not make the program outputs insert failed when the value of m for Line1 and Line2 are both 3. Note since I only compare the first value (i.e. m) in the operator== function in class Line, thus Line1 and Line2 in this code should have the same key. Shouldn't the insertion of an already existed key be invalid? Could some one explain why to me? Thanks!
#include<iostream>
#include<unordered_map>
using namespace std;
class Line {
public:
float m;
float c;
Line() {m = 0; c = 0;}
Line(float mInput, float cInput) {m = mInput; c = cInput;}
float getM() const {return m;}
float getC() const {return c;}
void setM(float mInput) {m = mInput;}
void setC(float cInput) {c = cInput;}
bool operator==(const Line &anotherLine) const
{
return (m == anotherLine.m);
}
};
namespace std
{
template <>
struct hash<Line>
{
size_t operator()(const Line& k) const
{
// Compute individual hash values for two data members and combine them using XOR and bit shifting
return ((hash<float>()(k.getM()) ^ (hash<float>()(k.getC()) << 1)) >> 1);
}
};
}
int main()
{
unordered_map<Line, int> t;
Line line1 = Line(3.0,4.0);
Line line2 = Line(3.0,5.0);
t.insert({line1, 1});
auto x = t.insert({line2, 2});
if (x.second == false)
cout << "insert failed" << endl;
for(unordered_map<Line, int>::const_iterator it = t.begin(); it != t.end(); it++)
{
Line t = it->first;
cout << t.m << " " << t.c << "\n" ;
}
return 1;
}
Your hash and operator == must satisfy a consistency requirement that they currently violate. When two objects are equal according to ==, their hash codes must be equal according to hash. In other words, while non-equal objects may have the same hash code, equal objects must have the same hash code:
size_t operator()(const Line& k) const {
return hash<float>()(k.getM());
}
Since you compare only one component for equality, and ignore the other component, you need to change your hash function to use the same component that you use to decide the equality.
you are using both the values of "m" and "c" in you hash, so 2 "Line" instances would have the same key if both their "m" and "c" are equal, which is not the case in your example. So if you do this :
Line line1 = Line(3.0,4.0);
Line line2 = Line(3.0,4.0);
t.insert({line1, 1});
auto x = t.insert({line2, 2});
if (x.second == false)
cout << "insert failed" << endl;
you'll see that it will print "insert failed"
You can always use custom function to compare the keys upon insertion:
#include <iostream>
#include <unordered_map>
class Line {
private:
float m;
float c;
public:
Line() { m = 0; c = 0; }
Line(float mInput, float cInput) { m = mInput; c = cInput; }
float getM() const { return m; }
float getC() const { return c; }
};
struct hash
{
size_t operator()(const Line& k) const
{
return ((std::hash<float>()(k.getM()) ^ (std::hash<float>()(k.getC()) << 1)) >> 1);
}
};
// custom key comparison
struct cmpKey
{
bool operator() (Line const &l1, Line const &l2) const
{
return l1.getM() == l2.getM();
}
};
int main()
{
std::unordered_map<Line, int, hash, cmpKey> mymap; // with custom key comparisom
Line line1 = Line(3.0, 4.0);
Line line2 = Line(4.0, 5.0);
Line line3 = Line(4.0, 4.0);
auto x = mymap.insert({ line1, 1 });
std::cout << std::boolalpha << "element inserted: " << x.second << std::endl;
x = mymap.insert({ line2, 2 });
std::cout << std::boolalpha << "element inserted: " << x.second << std::endl;
x = mymap.insert({ line3, 3 });
std::cout << std::boolalpha << "element inserted: " << x.second << std::endl;
return 0;
}
Prints:
element inserted: true
element inserted: true
element inserted: false
I cannot figure out why the algorithm results in an infinite loop. I am trying to sort the vector according to the final price. The pivot always stays the same. Maybe the problem is with the swapping of the objects
Motorbike findPivotPricee(vector<Motorbike*>& available, int left, int right)
{
int center = (left + right) / 2;
if (available[center]->finalPrice() < available[left]->finalPrice())
{
swap(*available[left], *available[center]);
}
if (available[right]->finalPrice()< available[left]->finalPrice())
{
swap(*available[left], *available[right]);
}
if (available[right]->finalPrice() < available[center]->finalPrice())
{
swap(*available[center], *available[right]);
}
Motorbike pivot = *available[center];
swap(*available[center], *available[right - 1]);
return pivot;
}
void quickSortMotorbikeByPrice(vector<Motorbike*>& available, int left, int right)
{
int i = left;
int j = right-1;
Motorbike pivot = findPivotPricee(available, left, right);
cout << pivot.finalPrice() << endl;
while (i < j)
{
while (available[i]->finalPrice() < pivot.finalPrice())
{
i++;
}
while (available[j]->finalPrice() > pivot.finalPrice())
{
j--;
}
if (i <= j)
{
swap(*available[i], *available[j]);
i++;
j--;
}
else {
break;
}
}
swap(*available[i], *available[right - 1]);//restore the pivot
if (left < right) {
if (left<j) quickSortMotorbikeByPrice(available, left, j);
if (right>i) quickSortMotorbikeByPrice(available, i, right);
}
}
void quickSortMotorbikeByPrice(vector<Motorbike*>& available)
{
quickSortMotorbikeByPrice(available, 0, available.size() - 1);
}
Often, algorithms from wikipedia, e.g. the quicksort algorithms are hard to transform into a working implementation because they fail to point out the assumed programming model implied by the given algorithm. For example, if it is a 0 based or a 1 based array and that they assume that the indices used are signed not unsigned integers.
Then, people start trying to use those algorithms, here, for example in C++ and run into all sorts of problems. Quite a waste of time... And from looking at the code given in the question, I assume the author of the question tried to use info from wikipedia...
Since this is obviously homework, impress your teacher and use the code below. Quicksort is tricky to get right and it can take quite a while to find out if you should write lo = left + 1 or lo = left etc.
#include <cstdint>
#include <memory>
#include <vector>
#include <iostream>
#include <cassert>
template <class X>
void vswap(std::vector<X>& v, size_t i1, size_t i2)
{
X temp = v[i1];
v[i1] = v[i2];
v[i2] = temp;
}
template <typename X>
std::ostream& operator<<(std::ostream& stm, const std::vector<X>& v)
{
stm << "[|";
size_t i = 0;
for (auto& x : v)
{
if (0 == i)
stm << x;
else
stm << "; " << x;
i++;
}
stm << "|]";
return stm;
}
template <typename X>
std::ostream& operator<<(std::ostream& stm, const std::vector<X*>& v)
{
stm << "[|";
size_t i = 0;
for (auto& x : v)
{
if (0 == i)
if (nullptr == x) stm << "nullptr"; else stm << *x;
else
if (nullptr == x) stm << "; nullptr"; else stm << "; " << *x;
i++;
}
stm << "|]";
return stm;
}
template <class X, class Predicate>
size_t partition(std::vector<X> & v, Predicate p, size_t left, size_t right)
{
size_t boundary = left;
X x = v[boundary];
for (size_t i = left; i < right; i++)
{
if (p(v[i], x))
{
vswap(v, boundary, i);
boundary++;
}
}
return boundary;
}
template<class X, class Predicate>
void mysort(std::vector<X> & v, Predicate p, size_t left, size_t right)
{
//std::cout << "mysort: " << v << " " << left << " " << right << std::endl;
if ((right - left) > 1)
{
size_t boundary = partition(v, p, left, right);
//std::cout << "boundary = " << boundary << std::endl;
mysort(v, p, left, boundary);
mysort(v, p, boundary == left ? boundary + 1 : boundary, right);
}
}
class Motorbike
{
size_t m_id;
int32_t m_finalPrice;
public:
Motorbike()
: m_id(0)
, m_finalPrice(0)
{}
Motorbike(size_t id, int32_t finalPrice)
: m_id(id)
, m_finalPrice(finalPrice)
{}
void Id(size_t id)
{
m_id = id;
}
size_t Id() const
{
return m_id;
}
void Price(int32_t price)
{
m_finalPrice = price;
}
int32_t Price() const
{
return m_finalPrice;
}
};
std::ostream& operator<< (std::ostream& stm, const Motorbike& bike)
{
stm << "(" << bike.Id() << ", " << bike.Price() << ")";
return stm;
}
std::vector<Motorbike> randomBikes(size_t count, int32_t lowPrice = 100, int32_t highPrice = 1000)
{
std::vector<Motorbike> result;
result.resize(count);
for (size_t i = 0; i < count; i++)
{
result[i].Id(i);
result[i].Price(lowPrice + rand() * (highPrice - lowPrice) / RAND_MAX);
}
return result;
}
std::vector<Motorbike*> bikePointers(std::vector<Motorbike> & bikes)
{
std::vector<Motorbike*> result;
result.resize(bikes.size());
for (size_t i = 0; i < bikes.size(); i++)
{
result[i] = &bikes[i];
}
return result;
}
int main()
{
//_CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF);
//_CrtDumpMemoryLeaks();
//{
//{
// std::vector<int32_t> data = { 3, 5, 1, 4, 2, 0 };
// std::cout << "original: " << data << std::endl;
// mysort(data, [](int32_t a, int32_t b) -> bool {return a < b;}, 0, data.size());
// std::cout << "sorted? " << data << std::endl;
//}
//std::cout << "--------------------------------------------------------" << std::endl;
//{
// std::vector<int32_t> data = { 3, 6, 1, 4, 2, 0, 5 };
// std::cout << "original: " << data << std::endl;
// mysort(data, [](int32_t a, int32_t b) -> bool {return a < b;}, 0, data.size());
// std::cout << "sorted? " << data << std::endl;
//}
for(size_t run = 0; run < 10; run++)
{
auto bikes = randomBikes(5+run%2);
auto bikes_p = bikePointers(bikes);
std::cout << "original: " << bikes_p << std::endl;
mysort(bikes_p, [](const Motorbike* m1, const Motorbike* m2)-> bool { return m1->Price() < m2->Price(); }, 0, bikes_p.size());
std::cout << "sorted? " << bikes_p << std::endl;
std::cout << "--------------------------------------------------------" << std::endl;
}
//}
//_CrtDumpMemoryLeaks();
return 0;
}
I'm working for my project of the end of the year with c++ language and I'm really stressed because I have 5 days in this error and there is no enough time . I hope you help me :
the error is:
no match for 'operator<<' in 'std::operator<< <std::char_traits<char> >((* &(& std::operator<< <std::char_traits<char> >((* & tempout.std::basic_ofstream<char>::<anonymous>), ((const char*)"Node ")))->std::basic_ostream<_CharT, _Traits>::operator<< <char, std::char_traits<char> >(i.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator-><Lattice<std::pair<std::vector<int>, std::vector<int> > >::Node*
the line of the error is : tempout<<"Node " << i->index << ": " <<i->c<<endl; and more sepifically in i->c
My code is the following:
//template named N
template<typename N>
//class latice that contains structure Node and other attribytes
class Lattice {
public:
int count; //count is incremented at every Node insertion in the latticeSet
typedef std::pair<std::vector<int>, std::vector<int> > Concept;
// Node is a set of concepts
//a latticeSet is a set of Node
struct Node {
int index;
typedef std::pair<std::vector<int>, std::vector<int> > Concept;
Node() {}; //constructor
Node(const N& con, int i) : c(con), index(i) {};
N c;
bool operator== (const Node& n) const { return c.first == n.c.first; }
std::pair<std::vector<int>,std::vector<int> > lowerUpperNeighbors;
};
std::vector<Node> latticeSet;//a set of Node
int last_position_cached;
bool was_insert_called;
Lattice() : count(0), last_position_cached(0), was_insert_called(false) {} //constructor
friend ostream& operator<< ( std::ostream& out,const Concept &c) {
out << "{";
if (c.first.size()!=0) {
for(std::vector<int>::const_iterator j = c.first.begin(); j < c.first.end() - 1; ++j)
out << *j << ", ";
out << *(c.first.end() - 1);
}
out << "}, {";
if (c.second.size()!=0) {
for(vector<int>::const_iterator j = c.second.begin(); j < c.second.end() - 1; ++j)
out << *j << ", ";
out << *(c.second.end() - 1);
}
out << "}";
return out;
}
/* The following method is a combination of both insert(x, L) and lookup(x, L) from the FCA Lattice Algorithm.
insertLookup takes a reference to a concept x, and c as input.
Concept x is an upper neighbor of c found by Neighbors, and c is the concept in which x was found to be its upper neighbor.
First, latticeSet is searched for the upper neighborx of c, and if it is not found then it is inserted in the lattice (same fashion as insert).
Next, the lattice is checked if it contains concept c, and if it does then the method returns false due to some unexpected case.
This condition is checked if insert was called, and if the last position of a concept cached by next is not equal to c.
Then, the lattice is searched for concept c in order to add its upper neighbor x.
Finally, concept x/c adds concept c/x as its lower/upper neighbor, respectively.
This method returns true if concept x was inserted in the lattice and c was added to its upper neighbors.
*/
bool insertLookup(const N& x, const N& c) {
std::vector<Node> latticeSet;
typename vector<Node>::iterator x_pos = find(latticeSet.begin(), latticeSet.end(), Node(x, count));
if (x_pos == latticeSet.end()) {
latticeSet.push_back(Node(x, count++));
x_pos = latticeSet.end() - 1;
}
typename vector<Node>::iterator c_pos;
if (was_insert_called && !(latticeSet[last_position_cached].c.first == c.first)) {
c_pos = find(latticeSet.begin(), latticeSet.end(), Node(c, count));
if (c_pos == latticeSet.end()) {
return false;
}
}
else
c_pos = latticeSet.begin() + last_position_cached;
x_pos->lowerUpperNeighbors.first.push_back(c_pos->index);
c_pos->lowerUpperNeighbors.second.push_back(x_pos->index);
return true;
}
//This method inserts a concept in the concept lattice.
bool insert(const N& c) {
latticeSet.push_back(Node(c, count++));
was_insert_called = true;
return true;
}
bool next(const N& c, N& output) {
typename vector<Node>::iterator pos = find(latticeSet.begin(), latticeSet.end(), Node(c, 0));
if (pos == latticeSet.end() || ++pos == latticeSet.end())
return false;
output = pos->c;
last_position_cached = pos - latticeSet.begin();
return true;
}
/* The following method is used to generate the required input file for graphplace.
printGraphplaceInput takes a reference to an output file stream out, and a flag (with a default value of zero).
First an output file stream tempout is in- stantiated with a file called “explain.graph” (see section 4.2).
If the flag passed is zero, then each Node’s concept of the latticeSet is printed to the lattice output file out;
else if the flag passed equals one, then each Node’s unique index number of the latticeSet is printed to the lattice output file out.
During the creation of the lattice output file, “explain.graph” is created by writing each Node index and its corresponding concept to tempout.
This method returns nothing.
*/
void printGraphplaceInput(ofstream& out, int flag = 1) {
ofstream tempout("explain.graph");
for (typename std::vector<Node>:: iterator i = latticeSet.begin(); i!=latticeSet.end();++i) {
//the error is here in i->c it doesn't work .and the error is that na match for operator<< and i didi'nt find a solution
tempout << "Node " << i->index << ": " << i->c <<endl;
out << "(";
if(flag == 0) {
cout << i->index << endl;
}
else if(flag == 1) {
out << i->index;
}
out << ") " << i->index << " node" << endl;
for (typename vector<int>::iterator j = i->lowerUpperNeighbors.second.begin(); j < i->lowerUpperNeighbors.second.end();++j)
out << *j << " " << i->index << " edge" << endl;
}
};
//get the size of the lattice
unsigned int getLatticeSize() {
return latticeSet.size();
}
void LatticeAlgorithm(const Context& GMI, Lattice<Concept>& L) {
vector<int> temp;
Concept c;
GMI.objDPrime((const vector<int>&) temp, c.first);
GMI.objPrime((const vector<int>&) temp, c.second);
L.insert(c);
neighbors n;
vector<Concept> neighborSet;
do {
n.Neighbors(c, GMI, neighborSet);
for(vector<Concept>::const_iterator x = neighborSet.begin(); x < neighborSet.end(); ++x) {
L.insertLookup(*x, c);
}
}
while(L.next(c, c));
}
My code keeps crashing and I believe it's because as i loop backwards in the insert function for Vector class, I decrement the iterator past the original pointer variable. Here's the insert function:
iterator insert(iterator & iter, const Object& obj){
if (theSize >= theCapacity){
resize(theSize+1);
int *p = iter;
for (iter; iter != this->end(); iter++){
//cout << "test1" << endl;
}
for (iter; iter != p; iter--){
*(iter-1) = *(iter-2);
cout << "test1" << endl;
//cout << *(iter - 2) << endl;
//cout << *(iter - 1) << endl;
}
}
else{
int *p = iter;
for (iter; iter != this->end(); iter++){
cout << "test" << endl;
}
for (iter; iter != p; iter--){
*(iter-1) = (*iter-2);
}
}
*iter = obj;
cout << theSize << endl << theCapacity << endl;
//theSize++;
return this->begin();
}
The goal of the insert function is to insert the object to the iterator position and in my code, i make sure that the Vector array is long enough and then I move every object in the array to the next indexed-space; and then I insert the object to the position designated by the iterator.
Also the entire Vector class is this:
#ifndef VECTOR_H
#define VECTOR_H
#include <algorithm>
#include <iostream>
template <typename Object>
class Vector
{
public:
explicit Vector(int initSize = 0)
: theSize{ initSize }, theCapacity{ initSize + SPARE_CAPACITY }
{
objects = new Object[theCapacity];
}
Vector(const Vector & rhs)
: theSize{ rhs.theSize }, theCapacity{ rhs.theCapacity }, objects{ nullptr }
{
objects = new Object[theCapacity];
for (int k = 0; k < theSize; ++k)
objects[k] = rhs.objects[k];
}
Vector & operator= (const Vector & rhs)
{
Vector copy = rhs;
std::swap(*this, copy);
return *this;
}
~Vector()
{
delete[] objects;
}
Vector(Vector && rhs)
: theSize{ rhs.theSize }, theCapacity{ rhs.theCapacity }, objects{ rhs.objects }
{
rhs.objects = nullptr;
rhs.theSize = 0;
rhs.theCapacity = 0;
}
Vector & operator= (Vector && rhs)
{
std::swap(theSize, rhs.theSize);
std::swap(theCapacity, rhs.theCapacity);
std::swap(objects, rhs.objects);
return *this;
}
bool empty() const
{
return size() == 0;
}
int size() const
{
return theSize;
}
int capacity() const
{
return theCapacity;
}
Object & operator[](int index)
{
return objects[index];
}
const Object & operator[](int index) const
{
return objects[index];
}
void resize(int newSize)
{
if (newSize > theCapacity)
reserve(newSize * 2);
theSize = newSize;
}
void reserve(int newCapacity)
{
if (newCapacity < theSize)
return;
Object *newArray = new Object[newCapacity];
for (int k = 0; k < theSize; ++k)
newArray[k] = std::move(objects[k]);
theCapacity = newCapacity;
std::swap(objects, newArray);
delete[] newArray;
}
// Stacky stuff
void push_back(const Object & x)
{
if (theSize == theCapacity)
reserve(2 * theCapacity + 1);
objects[theSize++] = x;
}
// Stacky stuff
void push_back(Object && x)
{
if (theSize == theCapacity)
reserve(2 * theCapacity + 1);
objects[theSize++] = std::move(x);
}
void pop_back()
{
--theSize;
}
const Object & back() const
{
return objects[theSize - 1];
}
// Iterator stuff: not bounds checked
typedef Object * iterator;
typedef const Object * const_iterator;
iterator begin()
{
return &objects[0];
}
const_iterator begin() const
{
return &objects[0];
}
iterator end()
{
return &objects[size()];
}
const_iterator end() const
{
return &objects[size()];
}
static const int SPARE_CAPACITY = 2;
iterator insert(iterator & iter, const Object& obj){
if (theSize >= theCapacity){
resize(theSize+1);
int *p = iter;
for (iter; iter != this->end(); iter++){
//cout << "test1" << endl;
}
for (iter; iter != p; iter--){
*(iter-1) = *(iter-2);
cout << "test1" << endl;
//cout << *(iter - 2) << endl;
//cout << *(iter - 1) << endl;
}
}
else{
int *p = iter;
for (iter; iter != this->end(); iter++){
cout << "test" << endl;
}
for (iter; iter != p; iter--){
*(iter-1) = (*iter-2);
}
}
*iter = obj;
cout << theSize << endl << theCapacity << endl;
//theSize++;
return this->begin();
}
iterator erase(iterator iter){
}
iterator find(iterator x, iterator y, const Object obj){
}
private:
int theSize;
int theCapacity;
Object * objects;
};
#endif
And my test file is this:
#include "Vector.h"
#include <iostream>
using namespace std;
int main(){
Vector<int> input;
Vector<int>::iterator iter;
int data = 0;
cout << "Enter five int digits: " << endl;
for (int i = 0; i < 5; i++){
cin >> data;
input.push_back(data);
}
data = 7654;
iter = input.begin();
iter++;
input.insert(iter, data);
for (iter = input.begin(); iter != input.end(); iter++){
cout << *iter << endl;
}
system("PAUSE");
}
Thanks to user4581301 and Igor's comments, I was able to solve it. You have to find the index of the iterator before it is lost when the array is resized. After resizing, set the iterator to the memory address of the object at the index. Like this:
if (theSize >= theCapacity){
int index = iter - this->begin();
resize(theSize+1);
iter = &objects[index];
int *p = iter;