more defensive checking for trivial types -- avoiding bugs

This commit is contained in:
Andrzej Krzemienski
2017-10-31 02:47:13 +01:00
parent 58f7c2f14a
commit a7f33f5d6f
3 changed files with 50 additions and 16 deletions

View File

@ -1,5 +1,5 @@
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
// Copyright (C) 2015 Andrzej Krzemienski. // Copyright (C) 2015 - 2017 Andrzej Krzemienski.
// //
// Use, modification, and distribution is subject to the Boost Software // Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -15,6 +15,7 @@
#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
@ -124,4 +125,30 @@
# define BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_FUNCTIONS # define BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_FUNCTIONS
#endif #endif
// 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
#endif
#ifdef BOOST_OPTIONAL_CONFIG_NO_POD_SPEC
# define BOOST_OPTIONAL_DETAIL_NO_POD_SPEC
#endif
#endif // header guard #endif // header guard

View File

@ -806,6 +806,7 @@ struct is_optional_val_init_candidate
{}; {};
#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
template <typename T> template <typename T>
struct is_type_trivially_copyable struct is_type_trivially_copyable
: boost::conditional<(boost::has_trivial_copy_constructor<T>::value && : boost::conditional<(boost::has_trivial_copy_constructor<T>::value &&
@ -815,6 +816,13 @@ struct is_type_trivially_copyable
boost::has_trivial_assign<T>::value), boost::has_trivial_assign<T>::value),
boost::true_type, boost::false_type>::type 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
@ -822,7 +830,7 @@ namespace optional_config {
template <typename T> template <typename T>
struct is_type_trivial struct is_type_trivial
: boost::conditional< (optional_detail::is_type_trivially_copyable<T>::value && boost::has_trivial_default_constructor<T>::value) || : boost::conditional< (optional_detail::is_type_trivially_copyable<T>::value && BOOST_HAS_TRIVIAL_CONSTRUCTOR(T)) ||
(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value) (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
{}; {};
@ -830,7 +838,7 @@ struct is_type_trivial
} // namespace optional_config } // namespace optional_config
#ifndef BOOST_OPTIONAL_CONFIG_NO_SPEC_FOR_TRIVIAL_TYPES #ifndef BOOST_OPTIONAL_DETAIL_NO_POD_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::is_type_trivial<T>::value, \
optional_detail::tc_optional_base<T>, \ optional_detail::tc_optional_base<T>, \
optional_detail::optional_base<T> \ optional_detail::optional_base<T> \

View File

@ -19,12 +19,7 @@
#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"
#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS #ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_FUNCTIONS
#if (defined BOOST_HAS_TRIVIAL_MOVE_ASSIGN) && (defined BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR) && (defined BOOST_HAS_TRIVIAL_CONSTRUCTOR) && (defined BOOST_HAS_TRIVIAL_COPY) && (defined BOOST_HAS_TRIVIAL_ASSIGN) && (defined BOOST_HAS_TRIVIAL_DESTRUCTOR)
#else
# define BOOST_OPTIONAL_NO_TRIVIALITY_DETECTION
#endif
struct PrivDefault struct PrivDefault
{ {
@ -77,9 +72,7 @@ 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::is_type_trivial<int> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial<double> )); BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial<double> ));
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_config::is_type_trivial<CustomizedTrivial> )); BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial<CustomizedTrivial> ));
@ -95,11 +88,17 @@ void test_type_traits()
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> ));
#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> > ));
#ifndef BOOST_OPTIONAL_NO_TRIVIALITY_DETECTION
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<PrivDefault> )); 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<NoDefault> ));
BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<CustDefault> )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable<CustDefault> ));
@ -118,7 +117,7 @@ void test_trivial_copyability()
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<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_TRUE((boost::is_base_of<boost::optional_detail::tc_optional_base<CustomizedTrivial>, boost::optional<CustomizedTrivial> > ));
#ifndef BOOST_OPTIONAL_NO_TRIVIALITY_DETECTION #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<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> > ));
@ -132,7 +131,7 @@ void test_trivial_copyability()
int main() int main()
{ {
#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS #ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_FUNCTIONS
test_type_traits(); test_type_traits();
test_trivial_copyability(); test_trivial_copyability();
#endif #endif