forked from boostorg/optional
Disabled assignment and construction from rvalue references in optional<const T&>
This commit is contained in:
@ -29,7 +29,9 @@
|
|||||||
#include <boost/type_traits/remove_reference.hpp>
|
#include <boost/type_traits/remove_reference.hpp>
|
||||||
#include <boost/type_traits/decay.hpp>
|
#include <boost/type_traits/decay.hpp>
|
||||||
#include <boost/type_traits/is_base_of.hpp>
|
#include <boost/type_traits/is_base_of.hpp>
|
||||||
|
#include <boost/type_traits/is_lvalue_reference.hpp>
|
||||||
#include <boost/type_traits/is_reference.hpp>
|
#include <boost/type_traits/is_reference.hpp>
|
||||||
|
#include <boost/type_traits/is_rvalue_reference.hpp>
|
||||||
#include <boost/type_traits/is_same.hpp>
|
#include <boost/type_traits/is_same.hpp>
|
||||||
#include <boost/mpl/if.hpp>
|
#include <boost/mpl/if.hpp>
|
||||||
#include <boost/mpl/bool.hpp>
|
#include <boost/mpl/bool.hpp>
|
||||||
@ -146,6 +148,7 @@ struct types_when_isnt_ref
|
|||||||
typedef T * pointer_type ;
|
typedef T * pointer_type ;
|
||||||
typedef T const& argument_type ;
|
typedef T const& argument_type ;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
struct types_when_is_ref
|
struct types_when_is_ref
|
||||||
{
|
{
|
||||||
@ -162,6 +165,14 @@ struct types_when_is_ref
|
|||||||
typedef raw_type& argument_type ;
|
typedef raw_type& argument_type ;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
template <class To, class From>
|
||||||
|
void prevent_binding_rvalue_ref_to_optional_lvalue_ref()
|
||||||
|
{
|
||||||
|
BOOST_STATIC_ASSERT_MSG(
|
||||||
|
!boost::is_lvalue_reference<To>::value || !boost::is_rvalue_reference<From>::value,
|
||||||
|
"binding rvalue references to optional lvalue references is disallowed");
|
||||||
|
}
|
||||||
|
|
||||||
struct optional_tag {} ;
|
struct optional_tag {} ;
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
@ -272,7 +283,7 @@ class optional_base : public optional_tag
|
|||||||
|
|
||||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
|
|
||||||
template<class Expr, typename PtrExpr>
|
template<class Expr, class PtrExpr>
|
||||||
explicit optional_base ( Expr&& expr, PtrExpr const* tag )
|
explicit optional_base ( Expr&& expr, PtrExpr const* tag )
|
||||||
:
|
:
|
||||||
m_initialized(false)
|
m_initialized(false)
|
||||||
@ -695,7 +706,8 @@ class optional : public optional_detail::optional_base<T>
|
|||||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
#ifndef BOOST_NO_CXX11_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( boost::forward<T>(val) )
|
||||||
|
{optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
|
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
|
||||||
@ -740,22 +752,23 @@ class optional : public optional_detail::optional_base<T>
|
|||||||
// even though explicit overloads are present for these.
|
// even though explicit overloads are present for these.
|
||||||
// Depending on the above some T ctor is called.
|
// Depending on the above some T ctor is called.
|
||||||
// Can throw if the resolved T ctor throws.
|
// Can throw if the resolved T ctor throws.
|
||||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
|
|
||||||
|
|
||||||
template<class Expr>
|
template<class Expr>
|
||||||
explicit optional ( Expr&& expr,
|
explicit optional ( Expr&& expr,
|
||||||
typename boost::disable_if_c<
|
BOOST_DEDUCED_TYPENAME boost::disable_if_c<
|
||||||
(boost::is_base_of<optional_detail::optional_tag, typename boost::decay<Expr>::type>::value) ||
|
(boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value) ||
|
||||||
boost::is_same<typename boost::decay<Expr>::type, none_t>::value >::type* = 0
|
boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value >::type* = 0
|
||||||
)
|
)
|
||||||
: base(boost::forward<Expr>(expr),boost::addressof(expr)) {}
|
: base(boost::forward<Expr>(expr),boost::addressof(expr))
|
||||||
|
{optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
template<class Expr>
|
template<class Expr>
|
||||||
explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
|
explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
|
||||||
#endif
|
#endif // !defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
#endif
|
#endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||||
|
|
||||||
// Creates a deep copy of another optional<T>
|
// Creates a deep copy of another optional<T>
|
||||||
// Can throw if T::T(T const&) does
|
// Can throw if T::T(T const&) does
|
||||||
@ -779,12 +792,14 @@ class optional : public optional_detail::optional_base<T>
|
|||||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
|
|
||||||
template<class Expr>
|
template<class Expr>
|
||||||
typename boost::disable_if_c<
|
BOOST_DEDUCED_TYPENAME boost::disable_if_c<
|
||||||
boost::is_base_of<optional_detail::optional_tag, typename boost::decay<Expr>::type>::value || boost::is_same<typename boost::decay<Expr>::type, none_t>::value,
|
boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value ||
|
||||||
|
boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value,
|
||||||
optional&
|
optional&
|
||||||
>::type
|
>::type
|
||||||
operator= ( Expr&& expr )
|
operator= ( Expr&& expr )
|
||||||
{
|
{
|
||||||
|
optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();
|
||||||
this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
|
this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
|
||||||
return *this ;
|
return *this ;
|
||||||
}
|
}
|
||||||
@ -836,7 +851,7 @@ class optional : public optional_detail::optional_base<T>
|
|||||||
return *this ;
|
return *this ;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
// Assigns from a T (deep-moves the rhs value)
|
// Assigns from a T (deep-moves the rhs value)
|
||||||
optional& operator= ( rval_reference_type val )
|
optional& operator= ( rval_reference_type val )
|
||||||
{
|
{
|
||||||
|
@ -32,5 +32,9 @@ import testing ;
|
|||||||
[ compile-fail optional_test_inplace_fail2.cpp ]
|
[ compile-fail optional_test_inplace_fail2.cpp ]
|
||||||
[ compile-fail optional_test_fail_copying_a_moveable_type.cpp ]
|
[ compile-fail optional_test_fail_copying_a_moveable_type.cpp ]
|
||||||
[ compile-fail optional_test_fail_optional_rvalue_ref.cpp ]
|
[ compile-fail optional_test_fail_optional_rvalue_ref.cpp ]
|
||||||
|
[ compile-fail optional_test_ref_fail_init_from_Trefref.cpp ]
|
||||||
|
[ compile-fail optional_test_ref_fail_init_from_Urefref.cpp ]
|
||||||
|
[ compile-fail optional_test_ref_fail_assign_from_Trefref.cpp ]
|
||||||
|
[ compile-fail optional_test_ref_fail_assign_from_Urefref.cpp ]
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
26
test/optional_test_ref_fail_assign_from_Trefref.cpp
Normal file
26
test/optional_test_ref_fail_assign_from_Trefref.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright (C) 2014, 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
|
||||||
|
//
|
||||||
|
#include "boost/optional.hpp"
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
|
//
|
||||||
|
// THIS TEST SHOULD FAIL TO COMPILE
|
||||||
|
//
|
||||||
|
void optional_reference__test_no_assign_from_Trefref()
|
||||||
|
{
|
||||||
|
boost::optional<const int&> opt;
|
||||||
|
opt = int(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error "Test skipped. This cannot be implemented w/o rvalue references."
|
||||||
|
#endif
|
26
test/optional_test_ref_fail_assign_from_Urefref.cpp
Normal file
26
test/optional_test_ref_fail_assign_from_Urefref.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright (C) 2014, 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
|
||||||
|
//
|
||||||
|
#include "boost/optional.hpp"
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
|
//
|
||||||
|
// THIS TEST SHOULD FAIL TO COMPILE
|
||||||
|
//
|
||||||
|
void optional_reference__test_no_assign_from_Urefref()
|
||||||
|
{
|
||||||
|
boost::optional<const int&> opt;
|
||||||
|
opt = long(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error "Test skipped. This cannot be implemented w/o rvalue references."
|
||||||
|
#endif
|
25
test/optional_test_ref_fail_init_from_Trefref.cpp
Normal file
25
test/optional_test_ref_fail_init_from_Trefref.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (C) 2014, 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
|
||||||
|
//
|
||||||
|
#include "boost/optional.hpp"
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
|
//
|
||||||
|
// THIS TEST SHOULD FAIL TO COMPILE
|
||||||
|
//
|
||||||
|
void optional_reference__test_no_init_from_Trefref()
|
||||||
|
{
|
||||||
|
boost::optional<const int&> opt = int(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error "Test skipped. This cannot be implemented w/o rvalue references."
|
||||||
|
#endif
|
25
test/optional_test_ref_fail_init_from_Urefref.cpp
Normal file
25
test/optional_test_ref_fail_init_from_Urefref.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (C) 2014, 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
|
||||||
|
//
|
||||||
|
#include "boost/optional.hpp"
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
|
//
|
||||||
|
// THIS TEST SHOULD FAIL TO COMPILE
|
||||||
|
//
|
||||||
|
void optional_reference__test_no_init_from_Urefref()
|
||||||
|
{
|
||||||
|
boost::optional<const int&> opt = long(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error "Test skipped. This cannot be implemented w/o rvalue references."
|
||||||
|
#endif
|
Reference in New Issue
Block a user