From 7a6d352ef5863939e4926738cbbbc46cf0d70bed Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 18 Apr 2015 18:08:48 +0200 Subject: [PATCH] code up the full virtual copy support policty decision logic still passes compilation, but not actually tested. The visitor-style accees needs to be implemented, and the whole virtual copy support mechanism extracted into a separate header and covered by unit test --- src/lib/variant.hpp | 237 ++++++++++++++++++++++++++------------------ 1 file changed, 138 insertions(+), 99 deletions(-) diff --git a/src/lib/variant.hpp b/src/lib/variant.hpp index ed03377b1..0ecf89a80 100644 --- a/src/lib/variant.hpp +++ b/src/lib/variant.hpp @@ -83,6 +83,9 @@ namespace lib { namespace { // implementation helpers using std::is_constructible; + using std::is_move_constructible; + using std::is_copy_constructible; + using std::is_copy_assignable; using std::remove_reference; using std::remove_const; using std::is_same; @@ -142,104 +145,21 @@ namespace lib { { }; - template - class FullCopySupport - : public B + + using EmptyBase = struct{}; + + template + class VirtualCopySupportInterface + : public BASE { - virtual void - copyInto (void* targetStorage) const override - { - D const& src = static_cast (*this); - new(targetStorage) D(src); - } - - virtual void - moveInto (void* targetStorage) override - { - D& src = static_cast (*this); - new(targetStorage) D(move(src)); - } - - virtual void - copyInto (B& target) const override - { - D& t = D::downcast(target); - D const& s = static_cast (*this); - t = s; - } - - virtual void - moveInto (B& target) override - { - D& t = D::downcast(target); - D& s = static_cast (*this); - t = move(s); - } + public: + virtual void copyInto (void* targetStorage) const =0; + virtual void moveInto (void* targetStorage) =0; + virtual void copyInto (IFA& target) const =0; + virtual void moveInto (IFA& target) =0; }; - template - class CloneSupport - : public B - { - virtual void - copyInto (void* targetStorage) const override - { - D const& src = static_cast (*this); - new(targetStorage) D(src); - } - - virtual void - moveInto (void* targetStorage) override - { - D& src = static_cast (*this); - new(targetStorage) D(move(src)); - } - - virtual void - copyInto (B&) const override - { - throw error::Logic("Assignment invoked but target is not assignable"); - } - - virtual void - moveInto (B&) override - { - throw error::Logic("Assignment invoked but target is not assignable"); - } - }; - - - template - class MoveSupport - : public B - { - virtual void - copyInto (void*) const override - { - throw error::Logic("Copy construction invoked but target allows only move construction"); - } - - virtual void - moveInto (void* targetStorage) override - { - D& src = static_cast (*this); - new(targetStorage) D(move(src)); - } - - virtual void - copyInto (B&) const override - { - throw error::Logic("Assignment invoked but target is not assignable"); - } - - virtual void - moveInto (B&) override - { - throw error::Logic("Assignment invoked but target is not assignable"); - } - }; - template class NoCopyMoveSupport @@ -271,6 +191,108 @@ namespace lib { }; + template + class MoveSupport + : NoCopyMoveSupport + { + virtual void + copyInto (void*) const override + { + throw error::Logic("Copy construction invoked but target allows only move construction"); + } + + virtual void + moveInto (void* targetStorage) override + { + D& src = static_cast (*this); + new(targetStorage) D(move(src)); + } + }; + + + template + class CloneSupport + : public MoveSupport + { + virtual void + copyInto (void* targetStorage) const override + { + D const& src = static_cast (*this); + new(targetStorage) D(src); + } + }; + + + template + class FullCopySupport + : public CloneSupport + { + virtual void + copyInto (B& target) const override + { + D& t = D::downcast(target); + D const& s = static_cast (*this); + t = s; + } + + virtual void + moveInto (B& target) override + { + D& t = D::downcast(target); + D& s = static_cast (*this); + t = move(s); + } + }; + + + + + /** workaround for GCC 4.7: need to exclude some types, + * since they raise private access violation during probing. + * Actually, in C++11 such a case should trigger substitution + * failure, not an compilation error */ + template + struct can_use_assignment + : is_copy_assignable + { }; + + template<> + struct can_use_assignment + { static constexpr bool value = false; }; + + + + template + struct use_if_supports_only_move + : enable_if< is_move_constructible::value + && !is_copy_constructible::value + && !can_use_assignment::value + ,X + > + { }; + + template + struct use_if_supports_cloning + : enable_if< is_move_constructible::value + && is_copy_constructible::value + && !can_use_assignment::value + ,X + > + { }; + + template + struct use_if_supports_copy_and_assignment + : enable_if< is_move_constructible::value + && is_copy_constructible::value + && !can_use_assignment::value + ,X + > + { }; + + + + + template struct CopySupport { @@ -278,6 +300,27 @@ namespace lib { using Policy = NoCopyMoveSupport; }; + template + struct CopySupport::type> + { + template + using Policy = MoveSupport; + }; + + template + struct CopySupport::type> + { + template + using Policy = CloneSupport; + }; + + template + struct CopySupport::type> + { + template + using Policy = FullCopySupport; + }; + }//(End) implementation helpers @@ -301,6 +344,7 @@ namespace lib { /** Inner capsule managing the contained object (interface) */ struct Buffer + : VirtualCopySupportInterface { char content_[SIZ]; @@ -309,11 +353,6 @@ namespace lib { virtual ~Buffer() {} ///< this is an ABC with VTable - virtual void copyInto (void* targetStorage) const =0; - virtual void moveInto (void* targetStorage) =0; - virtual void copyInto (Buffer& target) const =0; - virtual void moveInto (Buffer& target) =0; - };