From 0db9276e8c635c3d935287cb97accd94ed7ecd6c Mon Sep 17 00:00:00 2001
From: Daryle Walker
Date: Fri, 17 Feb 2012 01:55:33 +0000
Subject: [PATCH] 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]
---
base_from_member.html | 24 ++++----
include/boost/utility/base_from_member.hpp | 64 +++++++++++++++++++++-
2 files changed, 75 insertions(+), 13 deletions(-)
diff --git a/base_from_member.html b/base_from_member.html
index df4add2..07e144e 100644
--- a/base_from_member.html
+++ b/base_from_member.html
@@ -174,16 +174,18 @@ value of zero if it is omitted. The class template has a protected
data member called member that the derived class can use
for later base classes (or itself).
-If the variadic template arguments and r-value reference features of C++2011
-are present, there will be a single constructor template. It implements
-"perfect forwarding" to the best constructor call of
-member
(if any). The constructor template is marked both
-constexpr
and explicit
. The former will be ignored
-if the corresponding inner constructor call (of member
) does not
-have the marker. The latter binds the other way; always taking effect, even
-when the inner constructor call does not have the marker. The constructor
-template propagates the noexcept
status of the inner constructor
-call.
+If the appropriate features of C++2011 are present, there will be a single
+constructor template. It implements "perfect forwarding" to the best
+constructor call of member
(if any). The constructor template is
+marked both constexpr
and explicit
. The former will
+be ignored if the corresponding inner constructor call (of member
)
+does not have the marker. The latter binds the other way; always taking
+effect, even when the inner constructor call does not have the marker. The
+constructor template propagates the noexcept
status of the inner
+constructor call. (The constructor template has a trailing parameter with a
+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 base_from_member
.)
On earlier-standard compilers, there is a default constructor and several
constructor member templates. These constructor templates can take as many
@@ -385,7 +387,7 @@ a constructor call but std::nullptr_t
cannot.)
-Revised: 11 February 2012
+Revised: 16 February 2012
Copyright 2001, 2003, 2004, 2012 Daryle Walker. Use, modification, and distribution
are subject to the Boost Software License, Version 1.0. (See accompanying
diff --git a/include/boost/utility/base_from_member.hpp b/include/boost/utility/base_from_member.hpp
index 8148077..8d17522 100644
--- a/include/boost/utility/base_from_member.hpp
+++ b/include/boost/utility/base_from_member.hpp
@@ -15,6 +15,10 @@
#include
#include
#include
+#include
+#include
+#include
+#include
// Base-from-member arity configuration macro ------------------------------//
@@ -54,6 +58,59 @@
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::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::type,
+ typename ::boost::detail::remove_cv_ref::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
+struct enable_if_unrelated
+ : public ::boost::enable_if_c
+{};
+
+template
+struct enable_if_unrelated
+ : public ::boost::disable_if< ::boost::detail::is_related >
+{};
+#endif
+
+} // namespace boost::detail
+
+
// Base-from-member class template -----------------------------------------//
// Helper to initialize a base object so a derived class can use this
@@ -69,8 +126,11 @@ class base_from_member
protected:
MemberType member;
-#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
- template
+#if !defined(BOOST_NO_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_VARIADIC_TEMPLATES) && \
+ !defined(BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+ template ::type>
explicit BOOST_CONSTEXPR base_from_member( T&& ...x )
BOOST_NOEXCEPT_IF( BOOST_NOEXCEPT_EXPR(::new ((void*) 0) MemberType(
static_cast(x)... )) ) // no std::is_nothrow_constructible...