Reverted specialization for trivial types

It caused too many problems. I left only specialiation for scalar types.
I will need to devise clever type traits for reconizing trivial types with working constructor.
This commit is contained in:
Andrzej Krzemienski
2017-11-04 17:42:22 +01:00
parent cbf3cd05af
commit 06dea2cb9b
11 changed files with 293 additions and 123 deletions

View File

@ -10,7 +10,7 @@ Technical details aside, the memory layout of `optional<T>` for a generic `T` is
std::aligned_storage_t<sizeof(t), alignof(T)> _storage; std::aligned_storage_t<sizeof(t), alignof(T)> _storage;
}; };
Lifetime of the `T` inside `_storage` is manually controlled with placement-`new`s and pseudo-destructor calls. However, for trivial `T`s we use a different way of storage, by simply holding a `T`: Lifetime of the `T` inside `_storage` is manually controlled with placement-`new`s and pseudo-destructor calls. However, for scalar `T`s we use a different way of storage, by simply holding a `T`:
template <typename T> template <typename T>
class optional class optional
@ -19,7 +19,7 @@ Lifetime of the `T` inside `_storage` is manually controlled with placement-`new
T _storage; T _storage;
}; };
We call it a ['direct] storage. This makes `optional<T>` a trivially-copyable type for trivial `T`s. This only works for compilers that support defaulted functions and type traits. On compilers without defaulted functions we still use the direct storage, but `optional<T>` is no longer recognized as trivially-copyable. On compilers that do not fully support type traits, we still use the direct storage for scalar types, but we leave the programmer a way of customizing her type, so that it is reconized by `optional` as trivial, by specializing type trait `boost::opitonal_config::is_type_trivial`: We call it a ['direct] storage. This makes `optional<T>` a trivially-copyable type for scalar `T`s. This only works for compilers that support defaulted functions. On compilers without defaulted functions we still use the direct storage, but `optional<T>` is no longer recognized as trivially-copyable. Apart from scalar types, we leave the programmer a way of customizing her type, so that it is reconized by `optional` as candidate for optimized storage, by specializing type trait `boost::opitonal_config::optional_uses_direct_storage_for`:
struct X // not trivial struct X // not trivial
{ {
@ -28,7 +28,7 @@ We call it a ['direct] storage. This makes `optional<T>` a trivially-copyable ty
namespace boost { namespace optional_config { namespace boost { namespace optional_config {
template <> struct is_type_trivial<X> : boost::true_type {}; template <> struct optional_uses_direct_storage_for<X> : boost::true_type {};
}} }}

View File

@ -13,7 +13,7 @@
[heading Boost Release 1.66] [heading Boost Release 1.66]
* On newer compilers `optional` is now trivially-copyable for trivial `T`s. This uses a different storage (just `T` rather than `aligned_storage`). We require the compiler to support defaulted functions and type traits. Otherwise, we still use the the plain storage for scalar types. * On newer compilers `optional` is now trivially-copyable for scalar `T`s. This uses a different storage (just `T` rather than `aligned_storage`). We require the compiler to support defaulted functions.
[heading Boost Release 1.63] [heading Boost Release 1.63]

View File

@ -33,11 +33,10 @@
</h4> </h4>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"> <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
On newer compilers <code class="computeroutput"><span class="identifier">optional</span></code> On newer compilers <code class="computeroutput"><span class="identifier">optional</span></code>
is now trivially-copyable for trivial <code class="computeroutput"><span class="identifier">T</span></code>s. is now trivially-copyable for scalar <code class="computeroutput"><span class="identifier">T</span></code>s.
This uses a different storage (just <code class="computeroutput"><span class="identifier">T</span></code> This uses a different storage (just <code class="computeroutput"><span class="identifier">T</span></code>
rather than <code class="computeroutput"><span class="identifier">aligned_storage</span></code>). rather than <code class="computeroutput"><span class="identifier">aligned_storage</span></code>).
We require the compiler to support defaulted functions and type traits. We require the compiler to support defaulted functions.
Otherwise, we still use the the plain storage for scalar types.
</li></ul></div> </li></ul></div>
<h4> <h4>
<a name="boost_optional.relnotes.h1"></a> <a name="boost_optional.relnotes.h1"></a>

View File

@ -43,7 +43,7 @@
Lifetime of the <code class="computeroutput"><span class="identifier">T</span></code> inside Lifetime of the <code class="computeroutput"><span class="identifier">T</span></code> inside
<code class="computeroutput"><span class="identifier">_storage</span></code> is manually controlled <code class="computeroutput"><span class="identifier">_storage</span></code> is manually controlled
with placement-<code class="computeroutput"><span class="keyword">new</span></code>s and pseudo-destructor with placement-<code class="computeroutput"><span class="keyword">new</span></code>s and pseudo-destructor
calls. However, for trivial <code class="computeroutput"><span class="identifier">T</span></code>s calls. However, for scalar <code class="computeroutput"><span class="identifier">T</span></code>s
we use a different way of storage, by simply holding a <code class="computeroutput"><span class="identifier">T</span></code>: we use a different way of storage, by simply holding a <code class="computeroutput"><span class="identifier">T</span></code>:
</p> </p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span> <pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
@ -55,15 +55,13 @@
</pre> </pre>
<p> <p>
We call it a <span class="emphasis"><em>direct</em></span> storage. This makes <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code> a We call it a <span class="emphasis"><em>direct</em></span> storage. This makes <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code> a
trivially-copyable type for trivial <code class="computeroutput"><span class="identifier">T</span></code>s. trivially-copyable type for scalar <code class="computeroutput"><span class="identifier">T</span></code>s.
This only works for compilers that support defaulted functions and type traits. This only works for compilers that support defaulted functions. On compilers
On compilers without defaulted functions we still use the direct storage, without defaulted functions we still use the direct storage, but <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code> is
but <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code> is no longer recognized as trivially-copyable. Apart from scalar types, we leave
no longer recognized as trivially-copyable. On compilers that do not fully the programmer a way of customizing her type, so that it is reconized by
support type traits, we still use the direct storage for scalar types, but <code class="computeroutput"><span class="identifier">optional</span></code> as candidate for
we leave the programmer a way of customizing her type, so that it is reconized optimized storage, by specializing type trait <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">opitonal_config</span><span class="special">::</span><span class="identifier">optional_uses_direct_storage_for</span></code>:
by <code class="computeroutput"><span class="identifier">optional</span></code> as trivial, by
specializing type trait <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">opitonal_config</span><span class="special">::</span><span class="identifier">is_type_trivial</span></code>:
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">X</span> <span class="comment">// not trivial</span> <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">X</span> <span class="comment">// not trivial</span>
<span class="special">{</span> <span class="special">{</span>
@ -72,7 +70,7 @@
<span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">optional_config</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">optional_config</span> <span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;&gt;</span> <span class="keyword">struct</span> <span class="identifier">is_type_trivial</span><span class="special">&lt;</span><span class="identifier">X</span><span class="special">&gt;</span> <span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">true_type</span> <span class="special">{};</span> <span class="keyword">template</span> <span class="special">&lt;&gt;</span> <span class="keyword">struct</span> <span class="identifier">optional_uses_direct_storage_for</span><span class="special">&lt;</span><span class="identifier">X</span><span class="special">&gt;</span> <span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">true_type</span> <span class="special">{};</span>
<span class="special">}}</span> <span class="special">}}</span>
</pre> </pre>

View File

@ -146,7 +146,7 @@
</div> </div>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><p><small>Last revised: October 30, 2017 at 22:34:46 GMT</small></p></td> <td align="left"><p><small>Last revised: November 04, 2017 at 16:36:14 GMT</small></p></td>
<td align="right"><div class="copyright-footer"></div></td> <td align="right"><div class="copyright-footer"></div></td>
</tr></table> </tr></table>
<hr> <hr>

View File

@ -0,0 +1,98 @@
// Copyright (C) 2017 Andrzej Krzemienski.
//
// Use, modification, and distribution is subject to 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)
//
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
#ifndef BOOST_OPTIONAL_DETAIL_EXPERIMENTAL_TRAITS_04NOV2017_HPP
#define BOOST_OPTIONAL_DETAIL_EXPERIMENTAL_TRAITS_04NOV2017_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/type_traits.hpp>
namespace boost { namespace optional_detail {
// The condition to use POD implementation
#ifdef BOOST_OPTIONAL_CONFIG_NO_POD_SPEC
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif defined BOOST_OPTIONAL_CONFIG_NO_SPEC_FOR_TRIVIAL_TYPES
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif !defined BOOST_HAS_TRIVIAL_CONSTRUCTOR
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif !defined BOOST_HAS_TRIVIAL_MOVE_ASSIGN
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif !defined BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif !defined BOOST_HAS_TRIVIAL_COPY
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif !defined BOOST_HAS_TRIVIAL_ASSIGN
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif !defined BOOST_HAS_TRIVIAL_DESTRUCTOR
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif BOOST_WORKAROUND(BOOST_GCC, < 50000)
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#endif
#if __cplusplus >= 201103L
# if BOOST_WORKAROUND(BOOST_GCC, >= 50000)
# define BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS
# elif (defined BOOST_CLANG)
# define BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS
# endif
#endif
#ifndef BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS
# define BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T) BOOST_HAS_TRIVIAL_CONSTRUCTOR(T)
#else
# define BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T) std::is_trivially_default_constructible<T>::value
#endif
#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
template <typename T>
struct is_type_trivially_copyable
: boost::conditional<(boost::has_trivial_copy_constructor<T>::value &&
boost::has_trivial_move_constructor<T>::value &&
boost::has_trivial_destructor<T>::value &&
boost::has_trivial_move_assign<T>::value &&
boost::has_trivial_assign<T>::value),
boost::true_type, boost::false_type>::type
{};
#else
template <typename T>
struct is_type_trivially_copyable
: boost::conditional<(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value),
boost::true_type, boost::false_type>::type
{};
#endif
#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
template <typename T>
struct optional_uses_direct_storage_for_
: boost::conditional< (is_type_trivially_copyable<T>::value && BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T)) ||
(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value)
, boost::true_type, boost::false_type>::type
{};
#else
template <typename T>
struct optional_uses_direct_storage_for_
: boost::conditional<(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value)
, boost::true_type, boost::false_type>::type
{};
#endif
}} // boost::optional_detail
#endif

View File

@ -15,7 +15,6 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/detail/workaround.hpp> #include <boost/detail/workaround.hpp>
#include <boost/type_traits/intrinsics.hpp>
#if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (defined BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES) #if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (defined BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES)
# define BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES # define BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
@ -126,38 +125,8 @@
#endif #endif
// The condition to use POD implementation #ifdef BOOST_OPTIONAL_CONFIG_NO_DIRECT_STORAE_SPEC
# define BOOST_OPTIONAL_DETAIL_NO_DIRECT_STORAE_SPEC
#ifdef BOOST_OPTIONAL_CONFIG_NO_POD_SPEC
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif defined BOOST_OPTIONAL_CONFIG_NO_SPEC_FOR_TRIVIAL_TYPES
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif !defined BOOST_HAS_TRIVIAL_CONSTRUCTOR
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif !defined BOOST_HAS_TRIVIAL_MOVE_ASSIGN
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif !defined BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif !defined BOOST_HAS_TRIVIAL_COPY
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif !defined BOOST_HAS_TRIVIAL_ASSIGN
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif !defined BOOST_HAS_TRIVIAL_DESTRUCTOR
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#elif BOOST_WORKAROUND(BOOST_GCC, < 50000)
# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
#endif
#if __cplusplus >= 201103L
# if BOOST_WORKAROUND(BOOST_GCC, >= 50000)
# define BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS
# elif (defined BOOST_CLANG)
# define BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS
# endif
#endif
#ifdef BOOST_OPTIONAL_CONFIG_NO_POD_SPEC
# define BOOST_OPTIONAL_DETAIL_NO_POD_SPEC
#endif #endif

View File

@ -40,12 +40,6 @@
#include <boost/type_traits/remove_const.hpp> #include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp> #include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/decay.hpp> #include <boost/type_traits/decay.hpp>
#include <boost/type_traits/has_trivial_copy.hpp>
#include <boost/type_traits/has_trivial_move_constructor.hpp>
#include <boost/type_traits/has_trivial_constructor.hpp>
#include <boost/type_traits/has_trivial_assign.hpp>
#include <boost/type_traits/has_trivial_move_assign.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/type_traits/is_base_of.hpp> #include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/is_const.hpp> #include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_constructible.hpp> #include <boost/type_traits/is_constructible.hpp>
@ -809,55 +803,21 @@ struct is_optional_val_init_candidate
, boost::true_type, boost::false_type>::type , boost::true_type, boost::false_type>::type
{}; {};
#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
template <typename T>
struct is_type_trivially_copyable
: boost::conditional<(boost::has_trivial_copy_constructor<T>::value &&
boost::has_trivial_move_constructor<T>::value &&
boost::has_trivial_destructor<T>::value &&
boost::has_trivial_move_assign<T>::value &&
boost::has_trivial_assign<T>::value),
boost::true_type, boost::false_type>::type
{};
#else
template <typename T>
struct is_type_trivially_copyable
: boost::conditional<(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value),
boost::true_type, boost::false_type>::type
{};
#endif
} // namespace optional_detail } // namespace optional_detail
namespace optional_config { namespace optional_config {
#ifndef BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS
# define BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T) BOOST_HAS_TRIVIAL_CONSTRUCTOR(T)
#else
# define BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T) std::is_trivially_default_constructible<T>::value
#endif
#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
template <typename T> template <typename T>
struct is_type_trivial struct optional_uses_direct_storage_for
: boost::conditional< (optional_detail::is_type_trivially_copyable<T>::value && BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T)) ||
(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value)
, boost::true_type, boost::false_type>::type
{};
#else
template <typename T>
struct is_type_trivial
: boost::conditional<(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value) : boost::conditional<(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value)
, boost::true_type, boost::false_type>::type , boost::true_type, boost::false_type>::type
{}; {};
#endif
} // namespace optional_config } // namespace optional_config
#ifndef BOOST_OPTIONAL_DETAIL_NO_POD_SPEC #ifndef BOOST_OPTIONAL_DETAIL_NO_DIRECT_STORAE_SPEC
# define BOOST_OPTIONAL_BASE_TYPE(T) boost::conditional< optional_config::is_type_trivial<T>::value, \ # define BOOST_OPTIONAL_BASE_TYPE(T) boost::conditional< optional_config::optional_uses_direct_storage_for<T>::value, \
optional_detail::tc_optional_base<T>, \ optional_detail::tc_optional_base<T>, \
optional_detail::optional_base<T> \ optional_detail::optional_base<T> \
>::type >::type

View File

@ -76,6 +76,5 @@ import testing ;
[ run-fail optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp ] [ run-fail optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp ]
[ run optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp ] [ run optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp ]
[ compile-fail optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp ] [ compile-fail optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp ]
; ;
} }

View File

@ -0,0 +1,152 @@
// Copyright (C) 2017 Andrzej Krzemienski.
//
// Use, modification, and distribution is subject to 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)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
#include "boost/optional/optional.hpp"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "boost/core/lightweight_test.hpp"
#include "boost/core/lightweight_test_trait.hpp"
#include "boost/type_traits/is_base_of.hpp"
#include "boost/optional/detail/experimental_traits.hpp"
#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_FUNCTIONS
struct PrivDefault
{
private: PrivDefault() {}
};
struct CustDefault
{
CustDefault() {}
};
struct CustomizedTrivial
{
CustomizedTrivial() {}
};
struct DeletedDefault
{
BOOST_DELETED_FUNCTION(DeletedDefault())
};
namespace boost { namespace optional_config {
template <> struct optional_uses_direct_storage_for<CustomizedTrivial> : boost::true_type {};
}}
struct CustDtor
{
~CustDtor() {}
};
struct NoDefault
{
explicit NoDefault(int) {}
};
struct Empty {};
template <typename T, typename U>
struct Aggregate { T t; U u; };
struct CustAssign
{
CustAssign& operator=(CustAssign const&) { return *this; }
};
struct CustMove
{
CustMove(CustMove &&) {}
};
void test_type_traits()
{
// this only tests if type traits are implemented correctly
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for<int> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for<double> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for<CustomizedTrivial> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<PrivDefault> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<NoDefault> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<CustDefault> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<Aggregate<int, CustDefault> > ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<CustDtor> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<CustAssign> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<CustMove> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<Aggregate<int, CustMove> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<int> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<double> ));
#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for<Empty> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for<Aggregate<int, double> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for<Aggregate<Aggregate<Empty, int>, double> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<Empty> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<Aggregate<int, double> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<Aggregate<Aggregate<Empty, int>, double> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<PrivDefault> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<NoDefault> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<CustDefault> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<Aggregate<int, CustDefault> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<DeletedDefault> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<Aggregate<int, DeletedDefault> > ));
#endif
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<DeletedDefault> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<Aggregate<int, DeletedDefault> > ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable<CustDtor> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable<CustAssign> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable<CustMove> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable<Aggregate<int, CustMove> > ));
}
void test_trivial_copyability()
{
BOOST_TEST_TRAIT_TRUE((boost::is_base_of<boost::optional_detail::tc_optional_base<int>, boost::optional<int> > ));
BOOST_TEST_TRAIT_TRUE((boost::is_base_of<boost::optional_detail::tc_optional_base<double>, boost::optional<double> > ));
BOOST_TEST_TRAIT_TRUE((boost::is_base_of<boost::optional_detail::tc_optional_base<CustomizedTrivial>, boost::optional<CustomizedTrivial> > ));
BOOST_TEST_TRAIT_FALSE((boost::is_base_of<boost::optional_detail::tc_optional_base<DeletedDefault>, boost::optional<DeletedDefault> > ));
#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<int> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<double> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<CustomizedTrivial> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<Empty> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<Aggregate<int, double> > > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<Aggregate<Aggregate<Empty, int>, double> > > ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<DeletedDefault> > ));
#endif
}
#endif
int main()
{
#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_FUNCTIONS
test_type_traits();
test_trivial_copyability();
#endif
return boost::report_errors();
}

View File

@ -18,6 +18,7 @@
#include "boost/core/lightweight_test.hpp" #include "boost/core/lightweight_test.hpp"
#include "boost/core/lightweight_test_trait.hpp" #include "boost/core/lightweight_test_trait.hpp"
#include "boost/type_traits/is_base_of.hpp" #include "boost/type_traits/is_base_of.hpp"
#include "boost/optional/detail/experimental_traits.hpp"
#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_FUNCTIONS #ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_FUNCTIONS
@ -43,7 +44,7 @@ struct DeletedDefault
namespace boost { namespace optional_config { namespace boost { namespace optional_config {
template <> struct is_type_trivial<CustomizedTrivial> : boost::true_type {}; template <> struct optional_uses_direct_storage_for<CustomizedTrivial> : boost::true_type {};
}} }}
@ -75,44 +76,37 @@ struct CustMove
void test_type_traits() void test_type_traits()
{ {
// this only tests if type traits are implemented correctly // this only tests if type traits are implemented correctly
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial<int> )); BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for<int> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial<double> )); BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for<double> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial<CustomizedTrivial> )); BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for<CustomizedTrivial> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::is_type_trivial<PrivDefault> )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<PrivDefault> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::is_type_trivial<NoDefault> )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<NoDefault> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::is_type_trivial<CustDefault> )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<CustDefault> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::is_type_trivial<Aggregate<int, CustDefault> > )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<Aggregate<int, CustDefault> > ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::is_type_trivial<CustDtor> )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<CustDtor> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::is_type_trivial<CustAssign> )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<CustAssign> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::is_type_trivial<CustMove> )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<CustMove> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::is_type_trivial<Aggregate<int, CustMove> > )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<Aggregate<int, CustMove> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<int> )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<int> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<double> )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<double> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<Empty> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<Aggregate<int, double> > ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<Aggregate<Aggregate<Empty, int>, double> > ));
#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES #ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial<Empty> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial<Aggregate<int, double> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial<Aggregate<Aggregate<Empty, int>, double> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<Empty> )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<Empty> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<Aggregate<int, double> > )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<Aggregate<int, double> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<Aggregate<Aggregate<Empty, int>, double> > )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<Aggregate<Aggregate<Empty, int>, double> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<PrivDefault> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<NoDefault> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<CustDefault> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<Aggregate<int, CustDefault> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<DeletedDefault> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<Aggregate<int, DeletedDefault> > ));
#endif #endif
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::is_type_trivial<DeletedDefault> )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<DeletedDefault> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_config::is_type_trivial<Aggregate<int, DeletedDefault> > )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for<Aggregate<int, DeletedDefault> > ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable<CustDtor> )); BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable<CustDtor> ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable<CustAssign> )); BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable<CustAssign> ));
@ -131,12 +125,13 @@ void test_trivial_copyability()
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<int> > )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<int> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<double> > )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<double> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<CustomizedTrivial> > )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<CustomizedTrivial> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<Empty> > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<Aggregate<int, double> > > ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<Aggregate<Aggregate<Empty, int>, double> > > ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<DeletedDefault> > )); BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<DeletedDefault> > ));
#endif #endif
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<Empty> > ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<Aggregate<int, double> > > ));
BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable<boost::optional<Aggregate<Aggregate<Empty, int>, double> > > ));
} }
#endif #endif