diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f6912a9..7936ad7 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -76,6 +76,7 @@ import testing ; [ run optional_test_static_properties.cpp ] [ compile optional_test_maybe_uninitialized_warning.cpp ] [ compile optional_test_deleted_default_ctor.cpp ] + [ compile optional_test_constructible_from_other.cpp ] #[ run optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp ] [ run optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_pass.cpp ] [ run-fail optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp ] diff --git a/test/optional_test_constructible_from_other.cpp b/test/optional_test_constructible_from_other.cpp new file mode 100644 index 0000000..e106b69 --- /dev/null +++ b/test/optional_test_constructible_from_other.cpp @@ -0,0 +1,57 @@ +// Copyright (c) 2018 Andrey Semashev +// +// 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) + +// The test verifies that Boost.Optional copy constructors do not attempt to invoke +// the element type initializing constructors from templated arguments + +#include +#include + +struct no_type +{ + char data; +}; + +struct yes_type +{ + char data[2]; +}; + +template< unsigned int Size > +struct size_tag {}; + +template< typename T, typename U > +struct is_constructible +{ + template< typename T1, typename U1 > + static yes_type check_helper(size_tag< sizeof(static_cast< T1 >(U1())) >*); + template< typename T1, typename U1 > + static no_type check_helper(...); + + static const bool value = sizeof(check_helper< T, U >(0)) == sizeof(yes_type); +}; + +template< typename T > +class wrapper +{ +public: + wrapper() {} + wrapper(wrapper const&) {} + template< typename U > + wrapper(U const&, typename boost::enable_if_c< is_constructible< T, U >::value, int >::type = 0) {} +}; + +inline boost::optional< wrapper< int > > foo() +{ + return boost::optional< wrapper< int > >(); +} + +int main() +{ + // Invokes boost::optional copy constructor. Should not invoke wrapper constructor from U. + boost::optional< wrapper< int > > res = foo(); + return 0; +}