value constructor is sfinae-friendly

This commit is contained in:
Andrzej Krzemienski
2016-02-19 18:41:42 +01:00
parent 5ffa3fd2f6
commit f6e09fbf9c
6 changed files with 73 additions and 7 deletions

View File

@ -20,6 +20,7 @@
* you can swap optional references: it is like swapping pointers: shalow, underlying objects are not affected, * you can swap optional references: it is like swapping pointers: shalow, underlying objects are not affected,
* optional references to abstract types work. * optional references to abstract types work.
* Documented nested typedefs ([@https://svn.boost.org/trac/boost/ticket/5193 Trac #5193]). * Documented nested typedefs ([@https://svn.boost.org/trac/boost/ticket/5193 Trac #5193]).
* Made the optional value constructor SFINAE-friendly, which fixes [@https://svn.boost.org/trac/boost/ticket/12002 Trac #12002].
[heading Boost Release 1.60] [heading Boost Release 1.60]

View File

@ -60,6 +60,9 @@
Documented nested typedefs (<a href="https://svn.boost.org/trac/boost/ticket/5193" target="_top">Trac Documented nested typedefs (<a href="https://svn.boost.org/trac/boost/ticket/5193" target="_top">Trac
#5193</a>). #5193</a>).
</li> </li>
<li class="listitem">
Made the optional value constructor SFINAE-friendly, which fixes <a href="https://svn.boost.org/trac/boost/ticket/12002" target="_top">Trac #12002</a>.
</li>
</ul></div> </ul></div>
<h4> <h4>
<a name="boost_optional.relnotes.h1"></a> <a name="boost_optional.relnotes.h1"></a>

View File

@ -144,7 +144,7 @@
</div> </div>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><p><small>Last revised: February 18, 2016 at 23:24:54 GMT</small></p></td> <td align="left"><p><small>Last revised: February 19, 2016 at 17:38:50 GMT</small></p></td>
<td align="right"><div class="copyright-footer"></div></td> <td align="right"><div class="copyright-footer"></div></td>
</tr></table> </tr></table>
<hr> <hr>

View File

@ -37,6 +37,7 @@
#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_constructible.hpp>
#include <boost/type_traits/is_lvalue_reference.hpp> #include <boost/type_traits/is_lvalue_reference.hpp>
#include <boost/type_traits/is_nothrow_move_assignable.hpp> #include <boost/type_traits/is_nothrow_move_assignable.hpp>
#include <boost/type_traits/is_nothrow_move_constructible.hpp> #include <boost/type_traits/is_nothrow_move_constructible.hpp>
@ -565,17 +566,39 @@ class optional_base : public optional_tag
storage_type m_storage ; storage_type m_storage ;
} ; } ;
// definition of metafunciton is_optional_val_init_candidate
template <typename U> template <typename U>
struct is_optional_related struct is_optional_related
: boost::conditional<boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value : boost::conditional< boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
|| boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, none_t>::value, || boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<U>::type, none_t>::value,
boost::true_type, boost::false_type>::type boost::true_type, boost::false_type>::type
{}; {};
template <typename, typename U> #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500)
// this condition is a copy paste from is_constructible.hpp
template <typename T, typename U>
struct is_convertible_to_T_or_factory
: boost::conditional< boost::is_base_of<boost::in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
|| boost::is_base_of<boost::typed_in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
|| boost::is_constructible<T, U&&>::value
, boost::true_type, boost::false_type>::type
{};
#else
#define BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT
template <typename, typename>
struct is_convertible_to_T_or_factory : boost::true_type
{};
#endif // is_convertible condition
template <typename T, typename U>
struct is_optional_val_init_candidate struct is_optional_val_init_candidate
: boost::conditional<!is_optional_related<U>::value, boost::true_type, boost::false_type>::type : boost::conditional< !is_optional_related<U>::value && is_convertible_to_T_or_factory<T, U>::value
, boost::true_type, boost::false_type>::type
{}; {};
} // namespace optional_detail } // namespace optional_detail

View File

@ -39,6 +39,7 @@ import testing ;
[ run optional_test_emplace.cpp ] [ run optional_test_emplace.cpp ]
[ run optional_test_minimum_requirements.cpp ] [ run optional_test_minimum_requirements.cpp ]
[ run optional_test_msvc_bug_workaround.cpp ] [ run optional_test_msvc_bug_workaround.cpp ]
[ compile optional_test_sfinae_friendly_value_ctor.cpp ]
[ compile-fail optional_test_ref_convert_assign_const_int_prevented.cpp ] [ compile-fail optional_test_ref_convert_assign_const_int_prevented.cpp ]
[ compile-fail optional_test_fail1.cpp ] [ compile-fail optional_test_fail1.cpp ]
[ compile-fail optional_test_fail3a.cpp ] [ compile-fail optional_test_fail3a.cpp ]

View File

@ -0,0 +1,38 @@
// 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/optional.hpp"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
using boost::optional;
#if (!defined BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT)
struct X {};
struct Y {};
struct Resource
{
explicit Resource(const X&) {}
};
BOOST_STATIC_ASSERT(( boost::is_constructible<Resource, const X&>::value));
BOOST_STATIC_ASSERT((!boost::is_constructible<Resource, const Y&>::value));
BOOST_STATIC_ASSERT(( boost::is_constructible<optional<Resource>, const X&>::value));
BOOST_STATIC_ASSERT((!boost::is_constructible<optional<Resource>, const Y&>::value));
#endif
int main() { }