• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 // Copyright (C) 2008-2018 Lorenzo Caminiti
3 // Distributed under the Boost Software License, Version 1.0 (see accompanying
4 // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
5 // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
6 
7 #include <boost/contract.hpp>
8 #include <boost/optional.hpp>
9 #include <string>
10 #include <sstream>
11 #include <cassert>
12 
13 class lines {
14 public:
15     virtual std::string str(boost::contract::virtual_* v = 0) const = 0;
16     virtual std::string& str(boost::contract::virtual_* v = 0) = 0;
17 
18     virtual void put(std::string const& x,
19             boost::contract::virtual_* v = 0) = 0;
20 
21     virtual void put(char x, boost::contract::virtual_* v = 0) = 0;
22 
23     virtual void put(int x, bool tab = false,
24             boost::contract::virtual_* v = 0) = 0;
25 };
26 
str(boost::contract::virtual_ * v) const27 std::string lines::str(boost::contract::virtual_* v) const {
28     std::string result;
29     boost::contract::check c = boost::contract::public_function(v, result, this)
30         .postcondition([&] (std::string const& result) {
31             if(result != "") BOOST_CONTRACT_ASSERT(*result.rbegin() == '\n');
32         })
33     ;
34     assert(false);
35     return result;
36 }
37 
str(boost::contract::virtual_ * v)38 std::string& lines::str(boost::contract::virtual_* v) {
39     boost::optional<std::string&> result;
40     boost::contract::check c = boost::contract::public_function(v, result, this)
41         .postcondition([&] (boost::optional<std::string const&> const& result) {
42             if(*result != "") BOOST_CONTRACT_ASSERT(*result->rbegin() == '\n');
43         })
44     ;
45     assert(false);
46     return *result;
47 }
48 
put(std::string const & x,boost::contract::virtual_ * v)49 void lines::put(std::string const& x, boost::contract::virtual_* v) {
50     boost::contract::check c = boost::contract::public_function(v, this)
51         .precondition([&] {
52             BOOST_CONTRACT_ASSERT(*x.rbegin() != '\n');
53         })
54     ;
55     assert(false);
56 }
57 
put(char x,boost::contract::virtual_ * v)58 void lines::put(char x, boost::contract::virtual_* v) {
59     boost::contract::check c = boost::contract::public_function(v, this)
60         .precondition([&] {
61             BOOST_CONTRACT_ASSERT(x != '\n');
62         })
63     ;
64     assert(false);
65 }
66 
put(int x,bool tab,boost::contract::virtual_ * v)67 void lines::put(int x, bool tab,
68         boost::contract::virtual_* v) {
69     boost::contract::check c = boost::contract::public_function(v, this)
70         .precondition([&] {
71             BOOST_CONTRACT_ASSERT(x >= 0);
72         })
73     ;
74     assert(false);
75 }
76 
77 //[overload
78 class string_lines
79     #define BASES public lines
80     : BASES
81 {
82 public:
83     typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
84     #undef BASES
85 
BOOST_CONTRACT_OVERRIDES(str)86     BOOST_CONTRACT_OVERRIDES(str) // Invoked only once for all `str` overloads.
87 
88     std::string str(boost::contract::virtual_* v = 0) const /* override */ {
89         std::string result;
90         boost::contract::check c = boost::contract::public_function<
91                 override_str>(
92             v, result,
93             // `static_cast` resolves overloaded function pointer ambiguities.
94             static_cast<std::string (string_lines::*)(
95                     boost::contract::virtual_*) const>(&string_lines::str),
96             this
97         );
98 
99         return result = str_;
100     }
101 
102     // Overload on (absence of) `const` qualifier.
str(boost::contract::virtual_ * v=0)103     std::string& str(boost::contract::virtual_* v = 0) /* override */ {
104         boost::contract::check c = boost::contract::public_function<
105                 override_str>(
106             v, str_,
107             // `static_cast` resolves overloaded function pointer ambiguities.
108             static_cast<std::string& (string_lines::*)(
109                     boost::contract::virtual_*)>(&string_lines::str),
110             this
111         );
112 
113         return str_;
114     }
115 
BOOST_CONTRACT_OVERRIDES(put)116     BOOST_CONTRACT_OVERRIDES(put) // Invoked only once for all `put` overloads.
117 
118     void put(std::string const& x,
119             boost::contract::virtual_* v = 0) /* override */ {
120         boost::contract::old_ptr<std::string> old_str =
121                 BOOST_CONTRACT_OLDOF(v, str());
122         boost::contract::check c = boost::contract::public_function<
123                 override_put>(
124             v,
125             // `static_cast` resolves overloaded function pointer ambiguities.
126             static_cast<void (string_lines::*)(std::string const&,
127                     boost::contract::virtual_*)>(&string_lines::put),
128             this, x
129         )
130             .postcondition([&] {
131                 BOOST_CONTRACT_ASSERT(str() == *old_str + x + '\n');
132             })
133         ;
134 
135         str_ = str_ + x + '\n';
136     }
137 
138     // Overload on argument type.
put(char x,boost::contract::virtual_ * v=0)139     void put(char x, boost::contract::virtual_* v = 0) /* override */ {
140         boost::contract::old_ptr<std::string> old_str =
141                 BOOST_CONTRACT_OLDOF(v, str());
142         boost::contract::check c = boost::contract::public_function<
143                 override_put>(
144             v,
145             // `static_cast` resolves overloaded function pointer ambiguities.
146             static_cast<void (string_lines::*)(char,
147                     boost::contract::virtual_*)>(&string_lines::put),
148             this, x
149         )
150             .postcondition([&] {
151                 BOOST_CONTRACT_ASSERT(str() == *old_str + x + '\n');
152             })
153         ;
154 
155         str_ = str_ + x + '\n';
156     }
157 
158     // Overload on argument type and arity (also with default parameter).
put(int x,bool tab=false,boost::contract::virtual_ * v=0)159     void put(int x, bool tab = false,
160             boost::contract::virtual_* v = 0) /* override */ {
161         boost::contract::old_ptr<std::string> old_str =
162                 BOOST_CONTRACT_OLDOF(v, str());
163         boost::contract::check c = boost::contract::public_function<
164                 override_put>(
165             v,
166             // `static_cast` resolves overloaded function pointer ambiguities.
167             static_cast<void (string_lines::*)(int, bool,
168                     boost::contract::virtual_*)>(&string_lines::put),
169             this, x, tab
170         )
171             .postcondition([&] {
172                 std::ostringstream s;
173                 s << x;
174                 BOOST_CONTRACT_ASSERT(
175                         str() == *old_str + (tab ? "\t" : "") + s.str() + '\n');
176             })
177         ;
178 
179         std::ostringstream s;
180         s << str_ << (tab ? "\t" : "") << x << '\n';
181         str_ = s.str();
182     }
183 
184 private:
185     std::string str_;
186 };
187 //]
188 
main()189 int main() {
190     string_lines s;
191     s.put("abc");
192     assert(s.str() == "abc\n");
193     s.put('x');
194     assert(s.str() == "abc\nx\n");
195     s.put(10);
196     assert(s.str() == "abc\nx\n10\n");
197     s.put(20, true);
198     lines const& l = s;
199     assert(l.str() == "abc\nx\n10\n\t20\n");
200     return 0;
201 }
202 
203