にゃははー

はへらー

Perfect forwarding type II

オレツエーtype II

前スレ: Perfect forwarding!! - にゃははー

こっちの方がSFINAEの度合い的に問題なさそう・・・
ってかforwardの定義がすごい簡略化できた。

Index: boost/move/move.hpp
===================================================================
--- boost/move/move.hpp (revision 67436)
+++ boost/move/move.hpp (working copy)
@@ -27,9 +27,13 @@
 #include <memory>    //uninitialized_copy
 #include <iterator>  //std::iterator
 #include <boost/mpl/if.hpp>
+#include <boost/mpl/and.hpp>
 #include <boost/utility/enable_if.hpp>
 #include <boost/mpl/bool.hpp>
 #include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/is_lvalue_reference.hpp>
 #include <boost/utility/addressof.hpp>
 
 //! Defining or undefining this macro will change Boost.Move behaviour 
@@ -91,6 +95,16 @@
    enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) };
 };
 
+template < typename T >
+struct Move_ref_forwarding_
+{
+    T * const ptr;
+
+    explicit
+    Move_ref_forwarding_( T * const orig )
+      : ptr( orig ) {}
+};
+
 }  //namespace move_detail {
 INTERPROCESS_NAMESPACE_END
 }  //namespace boost {
@@ -130,20 +144,113 @@
 
 template <class T>
 struct is_rv
-{
-   static const bool value = false;
-};
+  : public ::boost::mpl::bool_< false > {};
 
 template <class T>
 struct is_rv< rv<T> >
+  : public ::boost::mpl::bool_< true > {};
+
+}  //namespace move_detail {
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//                            move_detail::is_rv_ref
+//
+//////////////////////////////////////////////////////////////////////////////
+
+namespace move_detail
 {
-   static const bool value = true;
+
+template < typename T >
+struct is_rv_ref
+  : public mpl::and_<
+      is_rv< typename remove_cv<
+        typename remove_reference< T >::type >::type >,
+      is_lvalue_reference< T > >::type {};
+
+} // namespace move_detail
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//                            move_detail::add_rv_ref
+//
+//////////////////////////////////////////////////////////////////////////////
+
+namespace move_detail
+{
+
+template < typename T, bool = is_lvalue_reference< T >::value >
+struct add_rv_ref;
+
+template < typename T >
+struct add_rv_ref< T, false >
+{
+    typedef ::BOOST_MOVE_NAMESPACE::rv< T > & type;
 };
 
-}  //namespace move_detail {
+template < typename T >
+struct add_rv_ref< const T, false >
+{
+    typedef const ::BOOST_MOVE_NAMESPACE::rv< T > & type;
+};
 
+template < typename T >
+struct add_rv_ref< volatile T, false >
+{
+    typedef volatile ::BOOST_MOVE_NAMESPACE::rv< T > & type;
+};
+
+template < typename T >
+struct add_rv_ref< const volatile T, false >
+{
+    typedef const volatile ::BOOST_MOVE_NAMESPACE::rv< T > & type;
+};
+
+} // namespace move_detail
+
 //////////////////////////////////////////////////////////////////////////////
 //
+//                            move_detail::remove_rv_ref
+//
+//////////////////////////////////////////////////////////////////////////////
+
+namespace move_detail
+{
+
+template < typename T >
+struct remove_rv_ref
+{
+    typedef T type;
+};
+
+template < typename T >
+struct remove_rv_ref< rv< T > & >
+{
+    typedef T type;
+};
+
+template < typename T >
+struct remove_rv_ref< const rv< T > & >
+{
+    typedef const T type;
+};
+
+template < typename T >
+struct remove_rv_ref< volatile rv< T > & >
+{
+    typedef volatile T type;
+};
+
+template < typename T >
+struct remove_rv_ref< const volatile rv< T > & >
+{
+    typedef const volatile T type;
+};
+
+} // namespace move_detail
+
+//////////////////////////////////////////////////////////////////////////////
+//
 //                               is_movable
 //
 //////////////////////////////////////////////////////////////////////////////
@@ -230,6 +337,7 @@
 //
 //////////////////////////////////////////////////////////////////////////////
 
+/* originals
 template <class T>
 typename enable_if< ::BOOST_MOVE_NAMESPACE::move_detail::is_rv<T>, T &>::type
    forward(const typename move_detail::identity<T>::type &x)
@@ -243,7 +351,26 @@
 {
    return x;
 }
+*/
 
+template < typename T >
+typename lazy_disable_if<
+  ::BOOST_MOVE_NAMESPACE::move_detail::is_rv_ref< T >,
+  ::BOOST_MOVE_NAMESPACE::move_detail::add_rv_ref< T > >::type
+forward(
+  ::BOOST_MOVE_NAMESPACE::move_detail::Move_ref_forwarding_<
+    typename ::BOOST_MOVE_NAMESPACE::move_detail::identity< T >::type > ref )
+{ return *ref.ptr; }
+
+template < typename T >
+typename enable_if<
+  ::BOOST_MOVE_NAMESPACE::move_detail::is_rv_ref< T >,
+  T >::type
+forward(
+  ::BOOST_MOVE_NAMESPACE::move_detail::Move_ref_forwarding_<
+    typename ::BOOST_MOVE_NAMESPACE::move_detail::remove_rv_ref< T >::type > ref )
+{ return *ref.ptr; }
+
 #else //BOOST_MOVE_OPTIMIZED_EMULATION
 
 #define BOOST_COPY_ASSIGN_REF(TYPE)\
@@ -348,6 +475,10 @@
    {  return *reinterpret_cast< ::BOOST_MOVE_NAMESPACE::rv<TYPE>* >(this);  }\
    operator const ::BOOST_MOVE_NAMESPACE::rv<TYPE>&() const \
    {  return *reinterpret_cast<const ::BOOST_MOVE_NAMESPACE::rv<TYPE>* >(this);  }\
+    operator ::BOOST_MOVE_NAMESPACE::move_detail::Move_ref_forwarding_< S >( void ) \
+    { return ::BOOST_MOVE_NAMESPACE::move_detail::Move_ref_forwarding_< S >( this ); } \
+    operator const ::BOOST_MOVE_NAMESPACE::move_detail::Move_ref_forwarding_< const S >( void ) const \
+    { return ::BOOST_MOVE_NAMESPACE::move_detail::Move_ref_forwarding_< const S >( this ); } \
    private:\
 //
 
@@ -368,6 +499,10 @@
    {  return *reinterpret_cast< ::BOOST_MOVE_NAMESPACE::rv<TYPE>* >(this);  }\
    operator const ::BOOST_MOVE_NAMESPACE::rv<TYPE>&() const \
    {  return *reinterpret_cast<const ::BOOST_MOVE_NAMESPACE::rv<TYPE>* >(this);  }\
+    operator ::BOOST_MOVE_NAMESPACE::move_detail::Move_ref_forwarding_< S >( void ) \
+    { return ::BOOST_MOVE_NAMESPACE::move_detail::Move_ref_forwarding_< S >( this ); } \
+    operator const ::BOOST_MOVE_NAMESPACE::move_detail::Move_ref_forwarding_< const S >( void ) const \
+    { return ::BOOST_MOVE_NAMESPACE::move_detail::Move_ref_forwarding_< const S >( this ); } \
    private:\
 //

アイディアのベースはstd::auto_ptrになってて、std::auto_ptrと違ってこっちは元クラスが正しくcopy/move-ctor/assignを定義/削除してるはずなので問題ないはず・・・
しかも変なSFINAEを使ってないからstd::auto_ptrの挙動を満たすコンパイラであれば基本的に動くはず。

例によってborlandとかmsvcとかのレビューくだしあ。
テストコードは前スレの奴がそのまま使えます。ってかC++0xで書いたコードが基本的にそのまま動く+正しくエラーを出すようになっていればおkです。

この流れならmove()も楽に作れそうだ・・・