## Modern C++ Design Pattern/Chatper 6. 어댑터

created : 2020-04-07T11:44:17+00:00
modified : 2020-09-26T14:19:03+00:00

• We use a example case, drawiing geometric shape.
  struct Point
{
int x, y;
};

struct Line{
Point start, end;
};

struct VectorObject
{
virtual std::vector<Line>::iterator begin() = 0;
virtual std::vector<Line>::iterator end() = 0;
};

struct VectorRectangle : VectorObject
{
VectorRectangle(int x, int y, int width, int height)
{
lines.emplace_back(Line{ Point{x, y}, Point{x + width, y} });
lines.emplace_back(Line{ Point{x + width, y}, Point {x + width, y + height} });
lines.emplace_back(Line{ Point{x,y}, Point{x, y + height} });
lines.emplace_back(Line{ Point{ x, y + height }, Point {x + width, y + height} });
}

std::vecotr<Line>::iterator begin() override {
return lines.begin();
}
std::vector<Line>::iterator end() override {
return lines.end();
}

private:
std::vector<Line> lines;
};

void DrawPoints(CPaintDC& dc,
std::vector<Point>::iterator start,
std::vector<Point>::iterator end)
{
for (auto i = start; i != end; ++i)
dc.SetPixel(i->x, i->y , 0);
}


• Let’s draw a few rectangles.
    vector<shared_ptr<VectorObject>> vectorObjects{
make_shared<VectorRectangle>(10, 10, 100, 100),
make_shared<VectorRectangle>(30, 30, 60, 60)
}

{
typedef vector<Point> Points;

virtual Points::iterator begin() { return points.begin(); }
virtual Points::iterator end() { return points.end(); }
private:
Points points;
};

{
int left = min(line.start.x, line.end.x);
int right = max(line.start.x, line.end.x);
int top = min(line.start.y, line.end.y);
int bottom = max(line.start.y, line.end.y);
int dx = right - left;
int dy = line.end.y - line.start.y;

if (dx == 0)
{
for (int y = top; y <= bottom; ++y)
{
points.emplace_back(Point{ left, y });
}
}
else if (dy == 0)
{
for (int x = left; x <= right; ++x)
{
points.emplace_back(Point{ x, top });
}
}
}

for (auto& obj : vectorObjects)
{
for (auto& line : *obj)
{
DrawPoints(dc, lpo.begin(), lpo.end());
}
}


• How about above method is called in every display update despite no change?
• One of the solutions is to use cache.

  vector<Point> points;
for (auto& o : vectorObjects)
{
for (auto& l : *o)
{
for (auto& p : lp)
points.push_back(p);
}
}

• Of course, this solution cause another problem. That is original vectorOjbects is changed.

  struct Point
{
int x, y;
friend std:: size_t hash_value(const POint& obj)
{
std::size_t send = 0x825C696F;
boost::hash_combine(seed, obj.x);
boost::hash_combine(seed, obj.y);
return seed;
}
};

struct Line
{
Point start, end;
friend std::size_t hash_value(const Line& obj)
{
std::size_t seed = 0x719E6B16;
boost::hash_combine(seed, obj.start);
boost::hash_combine(seed, obj.end);
return seed;
}
};

static map<size_t, Points> cache;

virtual Points::iterator begin() { return cache[line_hash].begin(); }
virtual Points::iterator end() { return cache[line_hash].end(); }