contract/example/features/overload.cpp
2017-12-10 16:31:15 -08:00

203 lines
6.3 KiB
C++

// Copyright (C) 2008-2018 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0 (see accompanying
// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
#include <boost/contract.hpp>
#include <boost/optional.hpp>
#include <string>
#include <sstream>
#include <cassert>
class lines {
public:
virtual std::string str(boost::contract::virtual_* v = 0) const = 0;
virtual std::string& str(boost::contract::virtual_* v = 0) = 0;
virtual void put(std::string const& x,
boost::contract::virtual_* v = 0) = 0;
virtual void put(char x, boost::contract::virtual_* v = 0) = 0;
virtual void put(int x, bool tab = false,
boost::contract::virtual_* v = 0) = 0;
};
std::string lines::str(boost::contract::virtual_* v) const {
std::string result;
boost::contract::check c = boost::contract::public_function(v, result, this)
.postcondition([&] (std::string const& result) {
if(result != "") BOOST_CONTRACT_ASSERT(*result.rbegin() == '\n');
})
;
assert(false);
return result;
}
std::string& lines::str(boost::contract::virtual_* v) {
boost::optional<std::string&> result;
boost::contract::check c = boost::contract::public_function(v, result, this)
.postcondition([&] (boost::optional<std::string const&> const& result) {
if(*result != "") BOOST_CONTRACT_ASSERT(*result->rbegin() == '\n');
})
;
assert(false);
return *result;
}
void lines::put(std::string const& x, boost::contract::virtual_* v) {
boost::contract::check c = boost::contract::public_function(v, this)
.precondition([&] {
BOOST_CONTRACT_ASSERT(*x.rbegin() != '\n');
})
;
assert(false);
}
void lines::put(char x, boost::contract::virtual_* v) {
boost::contract::check c = boost::contract::public_function(v, this)
.precondition([&] {
BOOST_CONTRACT_ASSERT(x != '\n');
})
;
assert(false);
}
void lines::put(int x, bool tab,
boost::contract::virtual_* v) {
boost::contract::check c = boost::contract::public_function(v, this)
.precondition([&] {
BOOST_CONTRACT_ASSERT(x >= 0);
})
;
assert(false);
}
//[overload
class string_lines
#define BASES public lines
: BASES
{
public:
typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
#undef BASES
BOOST_CONTRACT_OVERRIDES(str) // Invoked only once for all `str` overloads.
std::string str(boost::contract::virtual_* v = 0) const /* override */ {
std::string result;
boost::contract::check c = boost::contract::public_function<
override_str>(
v, result,
// `static_cast` resolves overloaded function pointer ambiguities.
static_cast<std::string (string_lines::*)(
boost::contract::virtual_*) const>(&string_lines::str),
this
);
return result = str_;
}
// Overload on (absence of) `const` qualifier.
std::string& str(boost::contract::virtual_* v = 0) /* override */ {
boost::contract::check c = boost::contract::public_function<
override_str>(
v, str_,
// `static_cast` resolves overloaded function pointer ambiguities.
static_cast<std::string& (string_lines::*)(
boost::contract::virtual_*)>(&string_lines::str),
this
);
return str_;
}
BOOST_CONTRACT_OVERRIDES(put) // Invoked only once for all `put` overloads.
void put(std::string const& x,
boost::contract::virtual_* v = 0) /* override */ {
boost::contract::old_ptr<std::string> old_str =
BOOST_CONTRACT_OLDOF(v, str());
boost::contract::check c = boost::contract::public_function<
override_put>(
v,
// `static_cast` resolves overloaded function pointer ambiguities.
static_cast<void (string_lines::*)(std::string const&,
boost::contract::virtual_*)>(&string_lines::put),
this, x
)
.postcondition([&] {
BOOST_CONTRACT_ASSERT(str() == *old_str + x + '\n');
})
;
str_ = str_ + x + '\n';
}
// Overload on argument type.
void put(char x, boost::contract::virtual_* v = 0) /* override */ {
boost::contract::old_ptr<std::string> old_str =
BOOST_CONTRACT_OLDOF(v, str());
boost::contract::check c = boost::contract::public_function<
override_put>(
v,
// `static_cast` resolves overloaded function pointer ambiguities.
static_cast<void (string_lines::*)(char,
boost::contract::virtual_*)>(&string_lines::put),
this, x
)
.postcondition([&] {
BOOST_CONTRACT_ASSERT(str() == *old_str + x + '\n');
})
;
str_ = str_ + x + '\n';
}
// Overload on argument type and arity (also with default parameter).
void put(int x, bool tab = false,
boost::contract::virtual_* v = 0) /* override */ {
boost::contract::old_ptr<std::string> old_str =
BOOST_CONTRACT_OLDOF(v, str());
boost::contract::check c = boost::contract::public_function<
override_put>(
v,
// `static_cast` resolves overloaded function pointer ambiguities.
static_cast<void (string_lines::*)(int, bool,
boost::contract::virtual_*)>(&string_lines::put),
this, x, tab
)
.postcondition([&] {
std::ostringstream s;
s << x;
BOOST_CONTRACT_ASSERT(
str() == *old_str + (tab ? "\t" : "") + s.str() + '\n');
})
;
std::ostringstream s;
s << str_ << (tab ? "\t" : "") << x << '\n';
str_ = s.str();
}
private:
std::string str_;
};
//]
int main() {
string_lines s;
s.put("abc");
assert(s.str() == "abc\n");
s.put('x');
assert(s.str() == "abc\nx\n");
s.put(10);
assert(s.str() == "abc\nx\n10\n");
s.put(20, true);
lines const& l = s;
assert(l.str() == "abc\nx\n10\n\t20\n");
return 0;
}