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
13class lines {
14public:
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
27std::string lines::str(boost::contract::virtual_* v) const {
28 std::string result;
29 boost::contract::check c = boost::contract::public_function(v, r&: result, obj: this)
30 .postcondition(f: [&] (std::string const& result) {
31 if(result != "") BOOST_CONTRACT_ASSERT(*result.rbegin() == '\n');
32 })
33 ;
34 assert(false);
35 return result;
36}
37
38std::string& lines::str(boost::contract::virtual_* v) {
39 boost::optional<std::string&> result;
40 boost::contract::check c = boost::contract::public_function(v, r&: result, obj: this)
41 .postcondition(f: [&] (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
49void lines::put(std::string const& x, boost::contract::virtual_* v) {
50 boost::contract::check c = boost::contract::public_function(v, obj: this)
51 .precondition(f: [&] {
52 BOOST_CONTRACT_ASSERT(*x.rbegin() != '\n');
53 })
54 ;
55 assert(false);
56}
57
58void lines::put(char x, boost::contract::virtual_* v) {
59 boost::contract::check c = boost::contract::public_function(v, obj: this)
60 .precondition(f: [&] {
61 BOOST_CONTRACT_ASSERT(x != '\n');
62 })
63 ;
64 assert(false);
65}
66
67void lines::put(int x, bool tab,
68 boost::contract::virtual_* v) {
69 boost::contract::check c = boost::contract::public_function(v, obj: this)
70 .precondition(f: [&] {
71 BOOST_CONTRACT_ASSERT(x >= 0);
72 })
73 ;
74 assert(false);
75}
76
77//[overload
78class string_lines
79 #define BASES public lines
80 : BASES
81{
82public:
83 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
84 #undef BASES
85
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, r&: 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 obj: this
97 );
98
99 return result = str_;
100 }
101
102 // Overload on (absence of) `const` qualifier.
103 std::string& str(boost::contract::virtual_* v = 0) /* override */ {
104 boost::contract::check c = boost::contract::public_function<
105 override_str>(
106 v, r&: str_,
107 // `static_cast` resolves overloaded function pointer ambiguities.
108 static_cast<std::string& (string_lines::*)(
109 boost::contract::virtual_*)>(&string_lines::str),
110 obj: this
111 );
112
113 return str_;
114 }
115
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 obj: this, args: x
129 )
130 .postcondition(f: [&] {
131 BOOST_CONTRACT_ASSERT(str() == *old_str + x + '\n');
132 })
133 ;
134
135 str_ = str_ + x + '\n';
136 }
137
138 // Overload on argument type.
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 obj: this, args&: x
149 )
150 .postcondition(f: [&] {
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).
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 obj: this, args&: x, args&: tab
170 )
171 .postcondition(f: [&] {
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
184private:
185 std::string str_;
186};
187//]
188
189int main() {
190 string_lines s;
191 s.put(x: "abc");
192 assert(s.str() == "abc\n");
193 s.put(x: 'x');
194 assert(s.str() == "abc\nx\n");
195 s.put(x: 10);
196 assert(s.str() == "abc\nx\n10\n");
197 s.put(x: 20, tab: true);
198 lines const& l = s;
199 assert(l.str() == "abc\nx\n10\n\t20\n");
200 return 0;
201}
202
203

source code of boost/libs/contract/example/features/overload.cpp