drop dependency on boost.detail

This commit is contained in:
Andrzej Krzemienski
2024-01-03 21:41:26 +01:00
parent a1dbd3b67d
commit 01e80d2b87
10 changed files with 34 additions and 257 deletions

View File

@ -17,7 +17,6 @@ The implementation uses the following other Boost modules:
# assert # assert
# config # config
# core # core
# detail
# move # move
# mpl # mpl
# static_assert # static_assert
@ -34,15 +33,15 @@ Certain constructors and functions in the interface of `optional` perform a 'per
template<class... Args> optional(in_place_init_t, Args&&... args); template<class... Args> optional(in_place_init_t, Args&&... args);
template<class... Args> optional(in_place_init_if_t, bool condition, Args&&... args); template<class... Args> optional(in_place_init_if_t, bool condition, Args&&... args);
template<class... Args> void emplace(Args&&... args); template<class... Args> void emplace(Args&&... args);
On compilers that do not support variadic templates, each of these functions is substituted with two overloads, one forwarding a single argument, the other forwarding zero arguments. This forms the following set: On compilers that do not support variadic templates, each of these functions is substituted with two overloads, one forwarding a single argument, the other forwarding zero arguments. This forms the following set:
template<class Arg> optional(in_place_init_t, Arg&& arg); template<class Arg> optional(in_place_init_t, Arg&& arg);
optional(in_place_init_t); optional(in_place_init_t);
template<class Arg> optional(in_place_init_if_t, bool condition, Arg&& arg); template<class Arg> optional(in_place_init_if_t, bool condition, Arg&& arg);
optional(in_place_init_if_t, bool condition); optional(in_place_init_if_t, bool condition);
template<class Arg> void emplace(Arg&& arg); template<class Arg> void emplace(Arg&& arg);
void emplace(); void emplace();
@ -51,16 +50,16 @@ On compilers that do not support rvalue references, each of these functions is s
template<class Arg> optional(in_place_init_t, const Arg& arg); template<class Arg> optional(in_place_init_t, const Arg& arg);
template<class Arg> optional(in_place_init_t, Arg& arg); template<class Arg> optional(in_place_init_t, Arg& arg);
optional(in_place_init_t); optional(in_place_init_t);
template<class Arg> optional(in_place_init_if_t, bool condition, const Arg& arg); template<class Arg> optional(in_place_init_if_t, bool condition, const Arg& arg);
template<class Arg> optional(in_place_init_if_t, bool condition, Arg& arg); template<class Arg> optional(in_place_init_if_t, bool condition, Arg& arg);
optional(in_place_init_if_t, bool condition); optional(in_place_init_if_t, bool condition);
template<class Arg> void emplace(const Arg& arg); template<class Arg> void emplace(const Arg& arg);
template<class Arg> void emplace(Arg& arg); template<class Arg> void emplace(Arg& arg);
void emplace(); void emplace();
This workaround addresses about 40% of all use cases. If this is insufficient, you need to resort to using [link boost_optional.tutorial.in_place_factories In-Place Factories]. This workaround addresses about 40% of all use cases. If this is insufficient, you need to resort to using [link boost_optional.tutorial.in_place_factories In-Place Factories].
[endsect] [endsect]
[section Optional Reference Binding][#optional_reference_binding] [section Optional Reference Binding][#optional_reference_binding]
@ -71,11 +70,11 @@ A number of compilers incorrectly treat const lvalues of integral type as rvalue
optional<const int&> or1; optional<const int&> or1;
optional<const int&> or2 = i; // caution: not portable optional<const int&> or2 = i; // caution: not portable
or1 = i; // caution: not portable or1 = i; // caution: not portable
optional<const int&> or3(i); // portable optional<const int&> or3(i); // portable
or1 = optional<const int&>(i); // portable or1 = optional<const int&>(i); // portable
Compilers known to have these deficiencies include GCC versions 4.2, 4.3, 4.4, 4.5, 5.1, 5.2; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, 11.0, 12.0. In order to check if your compiler correctly implements reference binding use this test program. Compilers known to have these deficiencies include GCC versions 4.2, 4.3, 4.4, 4.5, 5.1, 5.2; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, 11.0, 12.0. In order to check if your compiler correctly implements reference binding use this test program.
#include <cassert> #include <cassert>
@ -88,13 +87,13 @@ Compilers known to have these deficiencies include GCC versions 4.2, 4.3, 4.4, 4
assert(&ii == &global_i); assert(&ii == &global_i);
} }
void operator=(const int& ii) void operator=(const int& ii)
{ {
assert(&ii == &global_i); assert(&ii == &global_i);
} }
void operator=(int&&) // remove this if your compiler doesn't have rvalue refs void operator=(int&&) // remove this if your compiler doesn't have rvalue refs
{ {
assert(false); assert(false);
} }
}; };
@ -110,7 +109,7 @@ Compilers known to have these deficiencies include GCC versions 4.2, 4.3, 4.4, 4
TestingReferenceBinding ttt2 = iref; TestingReferenceBinding ttt2 = iref;
ttt2 = iref; ttt2 = iref;
} }
[endsect] [endsect]
[endsect] [endsect]

View File

@ -15,6 +15,7 @@
* Fixed the implementation for trivial types. Now it is slower, because it always initializes the `T`, but it avoids undefined behavior when `optional<T>` is copied. This fixes [@https://github.com/boostorg/optional/issues/108 issue #108]. * Fixed the implementation for trivial types. Now it is slower, because it always initializes the `T`, but it avoids undefined behavior when `optional<T>` is copied. This fixes [@https://github.com/boostorg/optional/issues/108 issue #108].
* Fixed some `-Wmaybe-uninitialized` warnings in GCC 12. Thanks to Christian Mazakas for the fix. * Fixed some `-Wmaybe-uninitialized` warnings in GCC 12. Thanks to Christian Mazakas for the fix.
* Dropped dependency on Boost.Detail.
[heading Boost Release 1.83] [heading Boost Release 1.83]

View File

@ -13,10 +13,10 @@
#define BOOST_OPTIONAL_DETAIL_EXPERIMENTAL_TRAITS_04NOV2017_HPP #define BOOST_OPTIONAL_DETAIL_EXPERIMENTAL_TRAITS_04NOV2017_HPP
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/detail/workaround.hpp> #include <boost/config/workaround.hpp>
#include <boost/predef.h> #include <boost/predef.h>
#include <boost/type_traits.hpp> #include <boost/type_traits.hpp>
// The condition to use POD implementation // The condition to use POD implementation
#ifdef BOOST_OPTIONAL_CONFIG_NO_POD_SPEC #ifdef BOOST_OPTIONAL_CONFIG_NO_POD_SPEC
@ -50,7 +50,7 @@
# define BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS # define BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS
# endif # endif
# endif # endif
#endif #endif
#ifndef BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS #ifndef BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS
@ -59,10 +59,10 @@
# include <type_traits> # include <type_traits>
# define BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T) std::is_trivially_default_constructible<T>::value # define BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T) std::is_trivially_default_constructible<T>::value
#endif #endif
namespace boost { namespace optional_detail { namespace boost { namespace optional_detail {
#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES #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
@ -83,7 +83,7 @@ struct is_type_trivially_copyable
#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES #ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES
template <typename T> template <typename T>
struct optional_uses_direct_storage_for_ struct optional_uses_direct_storage_for_
: boost::conditional< (is_type_trivially_copyable<T>::value && BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T)) || : boost::conditional< (is_type_trivially_copyable<T>::value && BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T)) ||

View File

@ -14,7 +14,7 @@
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_CONFIG_AJK_28JAN2015_HPP #define BOOST_OPTIONAL_DETAIL_OPTIONAL_CONFIG_AJK_28JAN2015_HPP
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/detail/workaround.hpp> #include <boost/config/workaround.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
@ -55,7 +55,7 @@
#if (defined(_MSC_VER) && _MSC_VER <= 1800) #if (defined(_MSC_VER) && _MSC_VER <= 1800)
// on MSVC 2013 and earlier an unwanted temporary is created when you assign from // on MSVC 2013 and earlier an unwanted temporary is created when you assign from
// a const lvalue of integral type. Thus we bind not to the original address but // a const lvalue of integral type. Thus we bind not to the original address but
// to a temporary. // to a temporary.
# define BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT # define BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT
#endif #endif

View File

@ -83,9 +83,6 @@ struct optional_value_type< ::boost::optional<T> >
}} // namespace boost::optional_detail }} // namespace boost::optional_detail
#ifdef BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL
#include <boost/optional/detail/old_optional_implementation.hpp>
#else
namespace boost { namespace boost {
namespace optional_ns { namespace optional_ns {
@ -1513,11 +1510,6 @@ class optional
BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
} ; } ;
} // namespace boost
#endif // BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL
namespace boost {
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
template<class T> template<class T>

View File

@ -44,7 +44,6 @@ import testing ;
[ run optional_test_io.cpp ] [ run optional_test_io.cpp ]
[ run optional_test_move.cpp ] [ run optional_test_move.cpp ]
[ run optional_test_noexcept_move.cpp ] [ run optional_test_noexcept_move.cpp ]
[ run optional_test_old_impl.cpp ]
[ run optional_test_equals_none.cpp ] [ run optional_test_equals_none.cpp ]
[ run optional_test_value_access.cpp ] [ run optional_test_value_access.cpp ]
[ run optional_test_emplace.cpp ] [ run optional_test_emplace.cpp ]

View File

@ -849,6 +849,8 @@ struct VBase : virtual X
VBase(int v) : X(v) {} VBase(int v) : X(v) {}
// MSVC 8.0 doesn't generate this correctly... // MSVC 8.0 doesn't generate this correctly...
VBase(const VBase& other) : X(static_cast<const X&>(other)) {} VBase(const VBase& other) : X(static_cast<const X&>(other)) {}
VBase& operator=(VBase const& rhs) { X::operator=(rhs); return *this; }
}; };
void test_with_class_type() void test_with_class_type()
@ -917,6 +919,7 @@ class CustomAddressOfClass
public: public:
CustomAddressOfClass() : n(0) {} CustomAddressOfClass() : n(0) {}
CustomAddressOfClass(CustomAddressOfClass const& that) : n(that.n) {} CustomAddressOfClass(CustomAddressOfClass const& that) : n(that.n) {}
CustomAddressOfClass& operator=(CustomAddressOfClass const& rhs) { n = rhs.n; return *this; }
explicit CustomAddressOfClass(int m) : n(m) {} explicit CustomAddressOfClass(int m) : n(m) {}
int* operator& () { return &n; } int* operator& () { return &n; }
bool operator== (CustomAddressOfClass const& that) const { return n == that.n; } bool operator== (CustomAddressOfClass const& that) const { return n == that.n; }

View File

@ -1,223 +0,0 @@
// Copyright (C) 2014 - 2018 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
#define BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL // does old implementation still work for basic usage?
#include "boost/optional/optional.hpp"
#ifdef BOOST_BORLANDC
#pragma hdrstop
#endif
#include "boost/core/ignore_unused.hpp"
#include "boost/core/lightweight_test.hpp"
using boost::optional;
struct IntWrapper
{
int _i;
IntWrapper(int i) : _i(i) {}
bool operator==(IntWrapper const& rhs) const { return _i == rhs._i; }
};
template <typename T>
void test_function_value_or_for()
{
optional<T> oM0;
const optional<T> oC0;
optional<T> oM1(1);
const optional<T> oC2(2);
BOOST_TEST(oM0.value_or(5) == 5);
BOOST_TEST(oC0.value_or(5) == 5);
BOOST_TEST(oM1.value_or(5) == 1);
BOOST_TEST(oC2.value_or(5) == 2);
}
template <typename T>
void test_function_value_for()
{
optional<T> o0;
optional<T> o1(1);
const optional<T> oC(2);
try
{
T& v = o1.value();
BOOST_TEST(v == 1);
}
catch(...)
{
BOOST_TEST(false);
}
try
{
T const& v = oC.value();
BOOST_TEST(v == 2);
}
catch(...)
{
BOOST_TEST(false);
}
BOOST_TEST_THROWS(o0.value(), boost::bad_optional_access);
}
void test_function_value()
{
test_function_value_for<int>();
test_function_value_for<double>();
test_function_value_for<IntWrapper>();
}
struct FatToIntConverter
{
static int conversions;
int _val;
FatToIntConverter(int val) : _val(val) {}
operator int() const { conversions += 1; return _val; }
};
int FatToIntConverter::conversions = 0;
void test_function_value_or()
{
test_function_value_or_for<int>();
test_function_value_or_for<double>();
test_function_value_or_for<IntWrapper>();
optional<int> oi(1);
BOOST_TEST(oi.value_or(FatToIntConverter(2)) == 1);
BOOST_TEST(FatToIntConverter::conversions == 0);
oi = boost::none;
BOOST_TEST(oi.value_or(FatToIntConverter(2)) == 2);
BOOST_TEST(FatToIntConverter::conversions == 1);
}
struct FunM
{
int operator()() { return 5; }
};
struct FunC
{
int operator()() const { return 6; }
};
int funP ()
{
return 7;
}
int throw_()
{
throw int();
}
void test_function_value_or_eval()
{
optional<int> o1 = 1;
optional<int> oN;
FunM funM;
FunC funC;
BOOST_TEST_EQ(o1.value_or_eval(funM), 1);
BOOST_TEST_EQ(oN.value_or_eval(funM), 5);
BOOST_TEST_EQ(o1.value_or_eval(FunM()), 1);
BOOST_TEST_EQ(oN.value_or_eval(FunM()), 5);
BOOST_TEST_EQ(o1.value_or_eval(funC), 1);
BOOST_TEST_EQ(oN.value_or_eval(funC), 6);
BOOST_TEST_EQ(o1.value_or_eval(FunC()), 1);
BOOST_TEST_EQ(oN.value_or_eval(FunC()), 6);
BOOST_TEST_EQ(o1.value_or_eval(funP), 1);
BOOST_TEST_EQ(oN.value_or_eval(funP), 7);
#ifndef BOOST_NO_CXX11_LAMBDAS
BOOST_TEST_EQ(o1.value_or_eval([](){return 8;}), 1);
BOOST_TEST_EQ(oN.value_or_eval([](){return 8;}), 8);
#endif
try
{
BOOST_TEST_EQ(o1.value_or_eval(throw_), 1);
}
catch(...)
{
BOOST_TEST(false);
}
BOOST_TEST_THROWS(oN.value_or_eval(throw_), int);
}
const optional<std::string> makeConstOptVal()
{
return std::string("something");
}
void test_const_move()
{
std::string s5 = *makeConstOptVal();
std::string s6 = makeConstOptVal().value();
boost::ignore_unused(s5);
boost::ignore_unused(s6);
}
#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
struct MoveOnly
{
explicit MoveOnly(int){}
MoveOnly(MoveOnly &&){}
void operator=(MoveOnly &&);
private:
MoveOnly(MoveOnly const&);
void operator=(MoveOnly const&);
};
optional<MoveOnly> makeMoveOnly()
{
return MoveOnly(1);
}
MoveOnly moveOnlyDefault()
{
return MoveOnly(1);
}
// compile-time test
void test_move_only_getters()
{
MoveOnly m1 = *makeMoveOnly();
MoveOnly m2 = makeMoveOnly().value();
MoveOnly m3 = makeMoveOnly().value_or(MoveOnly(1));
MoveOnly m4 = makeMoveOnly().value_or_eval(moveOnlyDefault);
boost::ignore_unused(m1);
boost::ignore_unused(m2);
boost::ignore_unused(m3);
boost::ignore_unused(m4);
}
#endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS
int main()
{
test_function_value();
test_function_value_or();
test_function_value_or_eval();
test_const_move();
return boost::report_errors();
}

View File

@ -53,6 +53,9 @@ namespace optional_swap_test
throw assignment_exception(); throw assignment_exception();
} }
base_class_with_forbidden_assignment() {}
base_class_with_forbidden_assignment(base_class_with_forbidden_assignment const&) {}
virtual ~base_class_with_forbidden_assignment() {} virtual ~base_class_with_forbidden_assignment() {}
}; };
@ -94,7 +97,8 @@ namespace optional_swap_test
class_whose_default_ctor_should_be_used() : data('\0') { } class_whose_default_ctor_should_be_used() : data('\0') { }
class_whose_default_ctor_should_be_used(const class_whose_default_ctor_should_be_used &) class_whose_default_ctor_should_be_used(const class_whose_default_ctor_should_be_used & rhs)
: base_class_with_forbidden_assignment(rhs)
{ {
BOOST_TEST(!"This copy constructor should not be used while swapping!"); BOOST_TEST(!"This copy constructor should not be used while swapping!");
throw copy_ctor_exception(); throw copy_ctor_exception();
@ -137,7 +141,8 @@ namespace optional_swap_test
throw default_ctor_exception(); throw default_ctor_exception();
} }
class_whose_explicit_ctor_should_be_used(const class_whose_explicit_ctor_should_be_used &) class_whose_explicit_ctor_should_be_used(const class_whose_explicit_ctor_should_be_used & rhs)
: base_class_with_forbidden_assignment(rhs)
{ {
BOOST_TEST(!"This copy constructor should not be used while swapping!"); BOOST_TEST(!"This copy constructor should not be used while swapping!");
throw copy_ctor_exception(); throw copy_ctor_exception();

View File

@ -123,6 +123,7 @@ void test_basics( )
optional<T> oa ( a ) ; optional<T> oa ( a ) ;
optional<T> ob ( a );
check_initialized(oa); check_initialized(oa);
oa = a ; oa = a ;
@ -132,7 +133,7 @@ void test_basics( )
optional<T> const oa2 ( oa ) ; optional<T> const oa2 ( oa ) ;
check_initialized_const(oa2); check_initialized_const(oa2);
oa = oa ; oa = ob ;
check_initialized(oa); check_initialized(oa);
oa = def ; oa = def ;