Fixed (hopefully) conflict between boost::base_from_member's C++11 constructor template and the automatically defined non-template copy- and/or move-constructors.

[SVN r77046]
This commit is contained in:
Daryle Walker 2012-02-17 01:55:33 +00:00
parent d6cb9a9176
commit 0db9276e8c
2 changed files with 75 additions and 13 deletions

View File

@ -174,16 +174,18 @@ value of zero if it is omitted. The class template has a protected
data member called <var>member</var> that the derived class can use data member called <var>member</var> that the derived class can use
for later base classes (or itself).</p> for later base classes (or itself).</p>
<p>If the variadic template arguments and r-value reference features of C++2011 <p>If the appropriate features of C++2011 are present, there will be a single
are present, there will be a single constructor template. It implements constructor template. It implements &quot;perfect forwarding&quot; to the best
&quot;perfect forwarding&quot; to the best constructor call of constructor call of <code>member</code> (if any). The constructor template is
<code>member</code> (if any). The constructor template is marked both marked both <code>constexpr</code> and <code>explicit</code>. The former will
<code>constexpr</code> and <code>explicit</code>. The former will be ignored be ignored if the corresponding inner constructor call (of <code>member</code>)
if the corresponding inner constructor call (of <code>member</code>) does not does not have the marker. The latter binds the other way; always taking
have the marker. The latter binds the other way; always taking effect, even effect, even when the inner constructor call does not have the marker. The
when the inner constructor call does not have the marker. The constructor constructor template propagates the <code>noexcept</code> status of the inner
template propagates the <code>noexcept</code> status of the inner constructor constructor call. (The constructor template has a trailing parameter with a
call.</p> default value that disables the template when its signature is too close to the
signatures of the automatically-defined non-template copy- and/or
move-constructors of <code>base_from_member</code>.)</p>
<p>On earlier-standard compilers, there is a default constructor and several <p>On earlier-standard compilers, there is a default constructor and several
constructor member templates. These constructor templates can take as many constructor member templates. These constructor templates can take as many
@ -385,7 +387,7 @@ a constructor call but <code>std::nullptr_t</code> cannot.)</p>
<hr> <hr>
<p>Revised: 11 February 2012</p> <p>Revised: 16 February 2012</p>
<p>Copyright 2001, 2003, 2004, 2012 Daryle Walker. Use, modification, and distribution <p>Copyright 2001, 2003, 2004, 2012 Daryle Walker. Use, modification, and distribution
are subject to the Boost Software License, Version 1.0. (See accompanying are subject to the Boost Software License, Version 1.0. (See accompanying

View File

@ -15,6 +15,10 @@
#include <boost/preprocessor/repetition/enum_binary_params.hpp> #include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp> #include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/enable_if.hpp>
// Base-from-member arity configuration macro ------------------------------// // Base-from-member arity configuration macro ------------------------------//
@ -54,6 +58,59 @@
namespace boost namespace boost
{ {
namespace detail
{
// Type-unmarking class template -------------------------------------------//
// Type-trait to get the raw type, i.e. the type without top-level reference nor
// cv-qualification, from a type expression. Mainly for function arguments, any
// reference part is stripped first.
// Contributed by Daryle Walker
template < typename T >
struct remove_cv_ref
{
typedef typename ::boost::remove_cv<typename
::boost::remove_reference<T>::type>::type type;
}; // boost::detail::remove_cv_ref
// Unmarked-type comparison class template ---------------------------------//
// Type-trait to check if two type expressions have the same raw type.
// Contributed by Daryle Walker, based on a work-around by Luc Danton
template < typename T, typename U >
struct is_related
: public ::boost::is_same<
typename ::boost::detail::remove_cv_ref<T>::type,
typename ::boost::detail::remove_cv_ref<U>::type >
{};
// Enable-if-on-unidentical-unmarked-type class template -------------------//
// Enable-if on the first two type expressions NOT having the same raw type.
// Contributed by Daryle Walker, based on a work-around by Luc Danton
#ifndef BOOST_NO_VARIADIC_TEMPLATES
template<typename ...T>
struct enable_if_unrelated
: public ::boost::enable_if_c<true>
{};
template<typename T, typename U, typename ...U2>
struct enable_if_unrelated<T, U, U2...>
: public ::boost::disable_if< ::boost::detail::is_related<T, U> >
{};
#endif
} // namespace boost::detail
// Base-from-member class template -----------------------------------------// // Base-from-member class template -----------------------------------------//
// Helper to initialize a base object so a derived class can use this // Helper to initialize a base object so a derived class can use this
@ -69,8 +126,11 @@ class base_from_member
protected: protected:
MemberType member; MemberType member;
#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL) #if !defined(BOOST_NO_RVALUE_REFERENCES) && \
template <typename ...T> !defined(BOOST_NO_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS)
template <typename ...T, typename EnableIf = typename
::boost::detail::enable_if_unrelated<base_from_member, T...>::type>
explicit BOOST_CONSTEXPR base_from_member( T&& ...x ) explicit BOOST_CONSTEXPR base_from_member( T&& ...x )
BOOST_NOEXCEPT_IF( BOOST_NOEXCEPT_EXPR(::new ((void*) 0) MemberType( BOOST_NOEXCEPT_IF( BOOST_NOEXCEPT_EXPR(::new ((void*) 0) MemberType(
static_cast<T&&>(x)... )) ) // no std::is_nothrow_constructible... static_cast<T&&>(x)... )) ) // no std::is_nothrow_constructible...