Skip to content

Commit

Permalink
Handle presence of various C++11 type traits (#58, thanks to @trapexit)
Browse files Browse the repository at this point in the history
  • Loading branch information
martinmoene committed Sep 7, 2020
1 parent af9f75d commit 7ea291a
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 28 deletions.
102 changes: 74 additions & 28 deletions include/nonstd/optional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,20 @@ namespace nonstd {
#define optional_HAVE_TR1_TYPE_TRAITS (!! optional_COMPILER_GNUC_VERSION )
#define optional_HAVE_TR1_ADD_POINTER (!! optional_COMPILER_GNUC_VERSION )

#define optional_HAVE_IS_ASSIGNABLE optional_CPP11_110
#define optional_HAVE_IS_MOVE_CONSTRUCTIBLE optional_CPP11_110
#define optional_HAVE_IS_NOTHROW_MOVE_ASSIGNABLE optional_CPP11_110
#define optional_HAVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE optional_CPP11_110

// clang < 3.5, gcc < 5.0, msvc < vc11 (vs12):
#define optional_HAVE_TRIV_CPMV_CONSTRUCTABLE \
( optional_CPP11_110 && \
!( optional_BETWEEN( optional_COMPILER_CLANG_VERSION, 1, 350 ) \
|| optional_BETWEEN( optional_COMPILER_GNUC_VERSION , 1, 500 ) ) )

#define optional_HAVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE optional_HAVE_TRIV_CPMV_CONSTRUCTABLE
#define optional_HAVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE optional_HAVE_TRIV_CPMV_CONSTRUCTABLE

// C++ feature usage:

#if optional_HAVE( CONSTEXPR_11 )
Expand Down Expand Up @@ -419,6 +433,12 @@ namespace nonstd { namespace optional_lite {

namespace std11 {

template< class T, T v > struct integral_constant { enum { value = v }; };
template< bool B > struct bool_constant : integral_constant<bool, B>{};

typedef bool_constant< true > true_type;
typedef bool_constant< false > false_type;

#if optional_CPP11_OR_GREATER
using std::move;
#else
Expand All @@ -432,16 +452,42 @@ namespace std11 {
template< typename T, typename F > struct conditional<false, T, F> { typedef F type; };
#endif // optional_HAVE_CONDITIONAL

// gcc < 5:
#if optional_CPP11_OR_GREATER
#if optional_BETWEEN( optional_COMPILER_GNUC_VERSION, 1, 500 )
template< typename T > struct is_trivially_copy_constructible : std::true_type{};
template< typename T > struct is_trivially_move_constructible : std::true_type{};
#if optional_HAVE( IS_ASSIGNABLE )
using std::is_assignable;
#else
template< class T > struct is_assignable : std11::true_type{};
#endif

#if optional_HAVE( IS_MOVE_CONSTRUCTIBLE )
using std::is_move_constructible;
#else
template< class T > struct is_move_constructible : std11::true_type{};
#endif

#if optional_HAVE( IS_NOTHROW_MOVE_ASSIGNABLE )
using std::is_nothrow_move_assignable;
#else
template< class T > struct is_nothrow_move_assignable : std11::true_type{};
#endif

#if optional_HAVE( IS_NOTHROW_MOVE_CONSTRUCTIBLE )
using std::is_nothrow_move_constructible;
#else
template< class T > struct is_nothrow_move_constructible : std11::true_type{};
#endif

#if optional_HAVE( IS_TRIVIALLY_COPY_CONSTRUCTIBLE )
using std::is_trivially_copy_constructible;
using std::is_trivially_move_constructible;
#else
template< class T > struct is_trivially_copy_constructible : std11::true_type{};
#endif

#if optional_HAVE( IS_TRIVIALLY_MOVE_CONSTRUCTIBLE )
using std::is_trivially_move_constructible;
#else
template< class T > struct is_trivially_move_constructible : std11::true_type{};
#endif

} // namespace std11

#if optional_CPP11_OR_GREATER
Expand All @@ -464,10 +510,10 @@ using std::swap;
struct is_swappable
{
template< typename T, typename = decltype( swap( std::declval<T&>(), std::declval<T&>() ) ) >
static std::true_type test( int /*unused*/ );
static std11::true_type test( int /*unused*/ );

template< typename >
static std::false_type test(...);
static std11::false_type test(...);
};

struct is_nothrow_swappable
Expand All @@ -481,10 +527,10 @@ struct is_nothrow_swappable
}

template< typename T >
static auto test( int /*unused*/ ) -> std::integral_constant<bool, satisfies<T>()>{}
static auto test( int /*unused*/ ) -> std11::integral_constant<bool, satisfies<T>()>{}

template< typename >
static auto test(...) -> std::false_type;
static auto test(...) -> std11::false_type;
};

} // namespace detail
Expand Down Expand Up @@ -891,13 +937,13 @@ class optional
// 3 (C++11) - move-construct from optional
template< typename U = T
optional_REQUIRES_T(
std::is_move_constructible<U>::value
std11::is_move_constructible<U>::value
|| std11::is_trivially_move_constructible<U>::value
)
>
optional_constexpr14 optional( optional && other )
// NOLINTNEXTLINE( performance-noexcept-move-constructor )
noexcept( std::is_nothrow_move_constructible<T>::value )
noexcept( std11::is_nothrow_move_constructible<T>::value )
: has_value_( other.has_value() )
{
if ( other.has_value() )
Expand Down Expand Up @@ -1101,8 +1147,8 @@ class optional
)
operator=( optional const & other )
noexcept(
std::is_nothrow_move_assignable<T>::value
&& std::is_nothrow_move_constructible<T>::value
std11::is_nothrow_move_assignable<T>::value
&& std11::is_nothrow_move_constructible<T>::value
)
#else
optional & operator=( optional const & other )
Expand All @@ -1121,7 +1167,7 @@ class optional
optional_REQUIRES_R(
optional &,
true
// std::is_move_constructible<T>::value
// std11::is_move_constructible<T>::value
// && std::is_move_assignable<T>::value
)
operator=( optional && other ) noexcept
Expand All @@ -1138,7 +1184,7 @@ class optional
optional_REQUIRES_R(
optional &,
std::is_constructible<T , U>::value
&& std::is_assignable<T&, U>::value
&& std11::is_assignable<T&, U>::value
&& !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
&& !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
&& !(std::is_scalar<T>::value && std::is_same<T, typename std::decay<U>::type>::value)
Expand Down Expand Up @@ -1176,7 +1222,7 @@ class optional
optional_REQUIRES_R(
optional&,
std::is_constructible< T , U const &>::value
&& std::is_assignable< T&, U const &>::value
&& std11::is_assignable< T&, U const &>::value
&& !std::is_constructible<T, optional<U> & >::value
&& !std::is_constructible<T, optional<U> && >::value
&& !std::is_constructible<T, optional<U> const & >::value
Expand All @@ -1185,10 +1231,10 @@ class optional
&& !std::is_convertible< optional<U> && , T>::value
&& !std::is_convertible< optional<U> const & , T>::value
&& !std::is_convertible< optional<U> const &&, T>::value
&& !std::is_assignable< T&, optional<U> & >::value
&& !std::is_assignable< T&, optional<U> && >::value
&& !std::is_assignable< T&, optional<U> const & >::value
&& !std::is_assignable< T&, optional<U> const && >::value
&& !std11::is_assignable< T&, optional<U> & >::value
&& !std11::is_assignable< T&, optional<U> && >::value
&& !std11::is_assignable< T&, optional<U> const & >::value
&& !std11::is_assignable< T&, optional<U> const && >::value
)
#else
optional&
Expand All @@ -1206,7 +1252,7 @@ class optional
optional_REQUIRES_R(
optional&,
std::is_constructible< T , U>::value
&& std::is_assignable< T&, U>::value
&& std11::is_assignable< T&, U>::value
&& !std::is_constructible<T, optional<U> & >::value
&& !std::is_constructible<T, optional<U> && >::value
&& !std::is_constructible<T, optional<U> const & >::value
Expand All @@ -1215,10 +1261,10 @@ class optional
&& !std::is_convertible< optional<U> && , T>::value
&& !std::is_convertible< optional<U> const & , T>::value
&& !std::is_convertible< optional<U> const &&, T>::value
&& !std::is_assignable< T&, optional<U> & >::value
&& !std::is_assignable< T&, optional<U> && >::value
&& !std::is_assignable< T&, optional<U> const & >::value
&& !std::is_assignable< T&, optional<U> const && >::value
&& !std11::is_assignable< T&, optional<U> & >::value
&& !std11::is_assignable< T&, optional<U> && >::value
&& !std11::is_assignable< T&, optional<U> const & >::value
&& !std11::is_assignable< T&, optional<U> const && >::value
)
operator=( optional<U> && other )
{
Expand Down Expand Up @@ -1260,7 +1306,7 @@ class optional
void swap( optional & other )
#if optional_CPP11_OR_GREATER
noexcept(
std::is_nothrow_move_constructible<T>::value
std11::is_nothrow_move_constructible<T>::value
&& std17::is_nothrow_swappable<T>::value
)
#endif
Expand Down Expand Up @@ -1626,7 +1672,7 @@ inline optional_constexpr bool operator>=( U const & v, optional<T> const & x )
template< typename T
#if optional_CPP11_OR_GREATER
optional_REQUIRES_T(
std::is_move_constructible<T>::value
std11::is_move_constructible<T>::value
&& std17::is_swappable<T>::value )
#endif
>
Expand Down
6 changes: 6 additions & 0 deletions test/optional-main.t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ CASE( "presence of C++ library features" "[.stdlibrary]" )
optional_PRESENT( optional_HAVE_TYPE_TRAITS );
optional_PRESENT( optional_HAVE_TR1_TYPE_TRAITS );
optional_PRESENT( optional_HAVE_TR1_ADD_POINTER );
optional_PRESENT( optional_HAVE_IS_ASSIGNABLE );
optional_PRESENT( optional_HAVE_IS_MOVE_CONSTRUCTIBLE );
optional_PRESENT( optional_HAVE_IS_NOTHROW_MOVE_ASSIGNABLE );
optional_PRESENT( optional_HAVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE );
optional_PRESENT( optional_HAVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE );
optional_PRESENT( optional_HAVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE );
#endif
#ifdef _HAS_CPP0X
optional_PRESENT( _HAS_CPP0X );
Expand Down

0 comments on commit 7ea291a

Please sign in to comment.