1 // Copyright (C) 2017 Andrzej Krzemienski.
2 //
3 // Use, modification, and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/optional for documentation.
8 //
9 // You are welcome to contact the author at:
10 //  [email protected]
11 
12 #ifndef BOOST_OPTIONAL_DETAIL_EXPERIMENTAL_TRAITS_04NOV2017_HPP
13 #define BOOST_OPTIONAL_DETAIL_EXPERIMENTAL_TRAITS_04NOV2017_HPP
14 
15 #include <boost/config.hpp>
16 #include <boost/detail/workaround.hpp>
17 #include <boost/predef.h>
18 #include <boost/type_traits.hpp>
19 
20 // The condition to use POD implementation
21 
22 #ifdef BOOST_OPTIONAL_CONFIG_NO_POD_SPEC
23 # define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
24 #elif defined BOOST_OPTIONAL_CONFIG_NO_SPEC_FOR_TRIVIAL_TYPES
25 # define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
26 #elif !defined BOOST_HAS_TRIVIAL_CONSTRUCTOR
27 # define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
28 #elif !defined BOOST_HAS_TRIVIAL_MOVE_ASSIGN
29 # define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
30 #elif !defined BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR
31 # define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
32 #elif !defined BOOST_HAS_TRIVIAL_COPY
33 # define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
34 #elif !defined BOOST_HAS_TRIVIAL_ASSIGN
35 # define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
36 #elif !defined BOOST_HAS_TRIVIAL_DESTRUCTOR
37 # define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
38 #elif BOOST_WORKAROUND(BOOST_GCC, < 50000)
39 # define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
40 #endif
41 
42 // GCC 5 or higher, or clang with libc++ or clang with libstdc++ 5 or higher
43 #if __cplusplus >= 201103L
44 #  if BOOST_WORKAROUND(BOOST_GCC, >= 50000)
45 #    define BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS
46 #  elif (defined BOOST_CLANG)
47 #    if BOOST_LIB_STD_CXX > 0
48 #      define BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS
49 #    elif BOOST_LIB_STD_GNU >= 441200023 && BOOST_LIB_STD_GNU != 450600023 && BOOST_LIB_STD_GNU != 450600026 && BOOST_LIB_STD_GNU != 460800003 && BOOST_LIB_STD_GNU != 450400026 && BOOST_LIB_STD_GNU != 460700026
50 #      define BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS
51 #    endif
52 #  endif
53 #endif
54 
55 
56 #ifndef BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS
57 #  define BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T) BOOST_HAS_TRIVIAL_CONSTRUCTOR(T)
58 #else
59 #  include <type_traits>
60 #  define BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T) std::is_trivially_default_constructible<T>::value
61 #endif
62 
63 
64 namespace boost { namespace optional_detail {
65 
66 #ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
67 template <typename T>
68 struct is_type_trivially_copyable
69   : boost::conditional<(boost::has_trivial_copy_constructor<T>::value &&
70                         boost::has_trivial_move_constructor<T>::value &&
71                         boost::has_trivial_destructor<T>::value &&
72                         boost::has_trivial_move_assign<T>::value &&
73                         boost::has_trivial_assign<T>::value),
74                         boost::true_type, boost::false_type>::type
75 {};
76 #else
77 template <typename T>
78 struct is_type_trivially_copyable
79 : boost::conditional<(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value),
80                      boost::true_type, boost::false_type>::type
81 {};
82 #endif
83 
84 
85 
86 #ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
87 template <typename T>
88 struct optional_uses_direct_storage_for_
89   : boost::conditional< (is_type_trivially_copyable<T>::value && BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T)) ||
90                         (boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value)
91                       , boost::true_type, boost::false_type>::type
92 {};
93 #else
94 template <typename T>
95 struct optional_uses_direct_storage_for_
96   : boost::conditional<(boost::is_scalar<T>::value && !boost::is_const<T>::value && !boost::is_volatile<T>::value)
97                       , boost::true_type, boost::false_type>::type
98 {};
99 #endif
100 
101 
102 }} // boost::optional_detail
103 
104 #endif
105