contract/test/old/copyable_traits.cpp
2017-12-10 16:31:15 -08:00

109 lines
2.7 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
// Test specializations of old value copy type traits.
#include <boost/contract/old.hpp>
#include <boost/type_traits.hpp>
#include <boost/noncopyable.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <cassert>
template<typename T>
void f(T& x) {
// No OLDOF here so C++11 not required for this test.
boost::contract::old_ptr_if_copyable<T> old_x = boost::contract::make_old(
boost::contract::copy_old() ? x : boost::contract::null_old());
}
// Test copyable type but...
struct w {
w() {}
w(w const&) { BOOST_TEST(false); } // Test this doesn't get copied.
};
// ...never copy old values for type `w` (because its copy is too expensive).
namespace boost { namespace contract {
template<>
struct is_old_value_copyable<w> : boost::false_type {};
} } // namespace
// Test non-copyable type but...
struct p : private boost::noncopyable { // Non-copyable via Boost.
static bool copied;
p() : num_(new int(0)) {}
~p() { delete num_; }
private:
int* num_;
friend struct boost::contract::old_value_copy<p>;
};
bool p::copied = false;
// ...still copy old values for type `p` (using a deep copy).
namespace boost { namespace contract {
template<>
struct old_value_copy<p> {
explicit old_value_copy(p const& old) {
*old_.num_ = *old.num_; // Deep copy pointed value.
p::copied = true;
}
p const& old() const { return old_; }
private:
p old_;
};
template<>
struct is_old_value_copyable<p> : boost::true_type {};
} } // namespace
// Non-copyable type so...
struct n {
n() {}
private:
n(n const&); // Non-copyable (but not via Boost).
};
// ...specialize `boost::is_copy_constructible` (no need for this on C++11).
namespace boost { namespace contract {
template<>
struct is_old_value_copyable<n> : boost::false_type {};
} } // namespace
int main() {
// NOTE: No test::detail::counter below because that is for copyable types.
{
int x; // Test has copy ctor so copy olds.
f(x);
}
{
w x; // Test has copy ctor but never copy olds (see TEST(...) above).
f(x);
}
p::copied = false;
{
p x; // Test no copy ctor but still old copies.
f(x);
}
#ifndef BOOST_CONTRACT_NO_OLDS
BOOST_TEST(p::copied);
#else
BOOST_TEST(!p::copied);
#endif
{
n x; // Test no copy ctor so no old copies.
f(x);
}
return boost::report_errors();
}