-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpolygon_solution.cpp
153 lines (128 loc) · 3.93 KB
/
polygon_solution.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright David Abrahams 2010. Distributed under the Boost
// Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <cstddef>
#include <cassert>
#include <iostream>
// Write a function template circumference that computes the
// circumference of a polygon
namespace unoptimized
{
template <class Polygon>
float circumference(Polygon const& p)
{
std::cout << "slow" << std::endl;
float ret = 0.0;
for (std::size_t i = 0, n = size(p); i < n; ++i)
ret += length(p,i);
return ret;
}
}
// Write another function template regular_circumference that
// computes the circumference of an regular polygon
template <class RegularPolygon>
float regular_circumference(RegularPolygon const& p)
{
std::cout << "fast" << std::endl;
return size(p) * side_length(p);
}
// From your two function implementations derive and define a Polygon
// concept, and its refinement RegularPolygon
//
// Polygon Requirements
//
// P: model of Polygon, x: object of type P, n: object of type size_t
// +-------------------+---------------+-----------------------+
// |Valid Expression |Type |Semantics / Pre / Post |
// +===================+===============+=======================+
// |size( x ) |std::size_t | |
// +-------------------+---------------+-----------------------+
// |length( x, n ) |float |Pre: n < size( x ) |
// +-------------------+---------------+-----------------------+
//
//
// RegularPolygon Requirements (in addition to Polygon)
//
// P: model of RegularPolygon, x: object of type P, n: object of type size_t
// +-------------------+---------------+-----------------------+
// |Valid Expression |Type |Semantics / Pre / Post |
// +===================+===============+=======================+
// |side_length( x ) | float |length(x, n) == |
// | | |side_length( x ) for |
// | | |all n < size( x ) |
// +-------------------+---------------+-----------------------+
//
// Extra Credit (hard): overload circumference so it uses
// regular_circumference on regular polygons
//
// Rectangle
//
struct rect
{
rect(float top, float left, float bottom, float right)
: top(top), left(left), bottom(bottom), right(right)
{}
float top, left, bottom, right;
};
inline float size(rect const& r)
{ return 4; }
inline float length(rect const& r, std::size_t side)
{ return side % 2 ? r.right - r.left : r.bottom - r.top; }
//
// Square
//
struct square
{
square(float top, float left, float dim)
: top(top), left(left), dim(dim)
{}
float top, left, dim;
};
inline float size(square const& r)
{ return 4; }
inline float side_length( square const& r )
{
return r.dim;
}
inline float length(square const& r, std::size_t side)
{
return side_length(r);
}
// Default implementation
template <class Polygon>
inline void* side_length( Polygon const& r )
{
return 0;
}
// Extra Credit (hard): overload circumference so it uses
// regular_circumference on regular polygons
namespace optimized
{
template <class Polygon>
float circumference_impl(Polygon const& p, void*)
{
return unoptimized::circumference( p );
}
template <class RegularPolygon>
float circumference_impl(RegularPolygon const& p, std::size_t)
{
return regular_circumference(p);
}
template <class Polygon>
float circumference(Polygon const& p)
{
return circumference_impl(p, side_length(p));
}
}
int main()
{
using optimized::circumference;
std::cout << "rect: ";
rect r(3, 4, 5, 9);
assert( circumference(r) == 14 );
std::cout << "square: ";
square s(0, 0, 5);
assert( circumference(s) == 20 );
std::cout << "explicit square: ";
assert( regular_circumference(s) == 20 );
}