forked from boostorg/optional
Fix for clang, when adapted type is convertible from other types.
The problem was with copy/move constructors of boost::optional<T>, which invoked optional_base<T> constructors with a single argument. Since optional_base has copy/move constructors along with initializing constructors taking a single argument, the latter may be considered by the compiler for viability. While doing so, the compiler may instantiate the template constructor of T with an argument of optional_base<T>, which in turn may fail if the constructor attempts to inspect the type of its argument (e.g. to constrain the set of acceptable types). Specifically, this happens with clang in C++03 mode, when boost::multiprecision::number is wrapped in boost::optional and a copy constructor of boost::optional is invoked. This commit fixes the problem by destinguishing copy/move constructors of optional_base from initializing constructors with an additional tag argument.
This commit is contained in:
@ -30,7 +30,7 @@ class tc_optional_base : public optional_tag
|
|||||||
:
|
:
|
||||||
m_initialized(false) {}
|
m_initialized(false) {}
|
||||||
|
|
||||||
tc_optional_base ( argument_type val )
|
tc_optional_base ( init_value_tag, argument_type val )
|
||||||
:
|
:
|
||||||
m_initialized(true), m_storage(val) {}
|
m_initialized(true), m_storage(val) {}
|
||||||
|
|
||||||
|
@ -107,6 +107,8 @@ using optional_ns::in_place_init_if;
|
|||||||
|
|
||||||
namespace optional_detail {
|
namespace optional_detail {
|
||||||
|
|
||||||
|
struct init_value_tag {};
|
||||||
|
|
||||||
struct optional_tag {};
|
struct optional_tag {};
|
||||||
|
|
||||||
|
|
||||||
@ -147,7 +149,7 @@ class optional_base : public optional_tag
|
|||||||
|
|
||||||
// Creates an optional<T> initialized with 'val'.
|
// Creates an optional<T> initialized with 'val'.
|
||||||
// Can throw if T::T(T const&) does
|
// Can throw if T::T(T const&) does
|
||||||
optional_base ( argument_type val )
|
optional_base ( init_value_tag, argument_type val )
|
||||||
:
|
:
|
||||||
m_initialized(false)
|
m_initialized(false)
|
||||||
{
|
{
|
||||||
@ -157,7 +159,7 @@ class optional_base : public optional_tag
|
|||||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||||
// move-construct an optional<T> initialized from an rvalue-ref to 'val'.
|
// move-construct an optional<T> initialized from an rvalue-ref to 'val'.
|
||||||
// Can throw if T::T(T&&) does
|
// Can throw if T::T(T&&) does
|
||||||
optional_base ( rval_reference_type val )
|
optional_base ( init_value_tag, rval_reference_type val )
|
||||||
:
|
:
|
||||||
m_initialized(false)
|
m_initialized(false)
|
||||||
{
|
{
|
||||||
@ -870,12 +872,12 @@ class optional
|
|||||||
|
|
||||||
// Creates an optional<T> initialized with 'val'.
|
// Creates an optional<T> initialized with 'val'.
|
||||||
// Can throw if T::T(T const&) does
|
// Can throw if T::T(T const&) does
|
||||||
optional ( argument_type val ) : base(val) {}
|
optional ( argument_type val ) : base(optional_detail::init_value_tag(), val) {}
|
||||||
|
|
||||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||||
// Creates an optional<T> initialized with 'move(val)'.
|
// Creates an optional<T> initialized with 'move(val)'.
|
||||||
// Can throw if T::T(T &&) does
|
// Can throw if T::T(T &&) does
|
||||||
optional ( rval_reference_type val ) : base( boost::forward<T>(val) )
|
optional ( rval_reference_type val ) : base(optional_detail::init_value_tag(), boost::forward<T>(val))
|
||||||
{}
|
{}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user