[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] master 69e4b2d9 2/2: Move semantics, adolescent
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] master 69e4b2d9 2/2: Move semantics, adolescent |
Date: |
Mon, 29 Aug 2022 13:14:55 -0400 (EDT) |
branch: master
commit 69e4b2d99677729723daed84fcff9bf5f9519782
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>
Move semantics, adolescent
---
smf.hpp | 30 ++++++++++++++++++++++++++++
smf_test.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 87 insertions(+), 7 deletions(-)
diff --git a/smf.hpp b/smf.hpp
index 531fd422..c51bd215 100644
--- a/smf.hpp
+++ b/smf.hpp
@@ -28,6 +28,36 @@
namespace smf_mechanics
{
+enum provenience
+ {extraordinary
+ ,default_constructed
+ ,copy_constructed
+ ,move_constructed
+ ,copy_assigned
+ ,move_assigned
+ };
+
+/// Detect another class's move and copy operations.
+///
+/// Add a data member of this class to the class to be instrumented
+/// (or, less plainly, inherit from it as a mixin).
+
+class sensor
+{
+ public:
+ sensor() : p_ {default_constructed} {}
+ ~sensor() = default;
+ sensor(sensor const&) : p_ {copy_constructed} {}
+ sensor(sensor&&) : p_ {move_constructed} {}
+ sensor& operator=(sensor const&) {p_ = copy_assigned; return *this;}
+ sensor& operator=(sensor&&) {p_ = move_assigned; return *this;}
+
+ provenience p() const {return p_;}
+
+ private:
+ provenience p_ {extraordinary};
+};
+
/// Induce ambiguity between a class's copy and move SMFs.
///
/// If class T has both a copy and a move ctor, both of which can be
diff --git a/smf_test.cpp b/smf_test.cpp
index f9750588..00c15748 100644
--- a/smf_test.cpp
+++ b/smf_test.cpp
@@ -70,6 +70,7 @@ struct no_can_move
struct A1111
{
+ smf_mechanics::sensor s;
};
static_assert(std::is_aggregate_v<A1111>);
@@ -81,6 +82,7 @@ struct C0000
C0000(C0000&&) = default;
C0000& operator=(C0000 const&) = default;
C0000& operator=(C0000&&) = default;
+ smf_mechanics::sensor s;
};
struct C0101
@@ -91,6 +93,7 @@ struct C0101
// C0101(C0101&&) // not declared
C0101& operator=(C0101 const&) = default;
// C0101& operator=(C0101&&) // not declared
+ smf_mechanics::sensor s;
};
struct C0202
@@ -99,6 +102,7 @@ struct C0202
~C0202() = default;
C0202(C0202 const&) = default;
C0202& operator=(C0202 const&) = default;
+ smf_mechanics::sensor s;
protected:
C0202(C0202&&) = default;
C0202& operator=(C0202&&) = default;
@@ -112,6 +116,7 @@ struct C0303
C0303(C0303&&) = delete;
C0303& operator=(C0303 const&) = default;
C0303& operator=(C0303&&) = delete;
+ smf_mechanics::sensor s;
};
#if defined LMI_CLANG
@@ -126,6 +131,7 @@ struct C0404 : public no_can_move
C0404(C0404&&) = default; // implicitly deleted
C0404& operator=(C0404 const&) = default;
C0404& operator=(C0404&&) = default; // implicitly deleted
+ smf_mechanics::sensor s;
};
struct C0505
@@ -136,6 +142,7 @@ struct C0505
C0505(C0505&&) = default;
C0505& operator=(C0505 const&) = default; // implicitly deleted
C0505& operator=(C0505&&) = default; // implicitly deleted
+ smf_mechanics::sensor s;
// reference or const member:
// - allows copy and move construction
// - inhibits copy and move assignment
@@ -154,8 +161,29 @@ struct C3030
C3030(C3030&&) = default;
C3030& operator=(C3030 const&) = delete;
C3030& operator=(C3030&&) = default;
+ smf_mechanics::sensor s;
};
+template<typename T>
+constexpr bool was_move_constructed_as_expected(T const& t)
+{
+ return
+ well_move_constructible<T>
+ ? smf_mechanics::move_constructed == t.s.p()
+ : smf_mechanics::copy_constructed == t.s.p()
+ ;
+}
+
+template<typename T>
+constexpr bool was_move_assigned_as_expected(T const& t)
+{
+ return
+ well_move_assignable<T>
+ ? smf_mechanics::move_assigned == t.s.p()
+ : smf_mechanics::copy_assigned == t.s.p()
+ ;
+}
+
/// Statically tested properties, encoded as bits in an 'int'.
///
/// There is no great advantage to representing this as a std::bitset.
@@ -202,6 +230,8 @@ constexpr int complexion()
/// Compile-time properties:
/// e: move construct compiles without error
/// f: move assign compiles without error
+/// g: move construct has move semantics
+/// h: move assign has move semantics
///
/// True by definition:
/// Wc ≡ Mc ∧ Ec
@@ -210,8 +240,8 @@ constexpr int complexion()
/// e ?≡ Mc
/// f ?≡ Ma
/// Ec ?≡ Ea [need example to falsify this]
-/// Wc ?≡ move construct has move semantics
-/// Wa ?≡ move assign has move semantics
+/// g ?≡ Wc
+/// h ?≡ Wa
void smf_test::test_classes()
{
@@ -263,22 +293,42 @@ void smf_test::test_classes()
A1111 u_A1111 {std::move(t_A1111)};
C0000 u_C0000 {std::move(t_C0000)};
C0101 u_C0101 {std::move(t_C0101)};
-// C0202 u_C0202 {std::move(t_C0202)}; // protected
-// C0303 u_C0303 {std::move(t_C0303)}; // deleted
+// C0202 u_C0202 {std::move(t_C0202)}; // !e: protected
+// C0303 u_C0303 {std::move(t_C0303)}; // !e: deleted
C0404 u_C0404 {std::move(t_C0404)};
C0505 u_C0505 {std::move(t_C0505)};
C3030 u_C3030 {std::move(t_C3030)};
+ // Test hypothesis: g ?≡ Wc
+ LMI_TEST(was_move_constructed_as_expected(u_A1111));
+ LMI_TEST(was_move_constructed_as_expected(u_C0000));
+ LMI_TEST(was_move_constructed_as_expected(u_C0101));
+// LMI_TEST(was_move_constructed_as_expected(u_C0202));
+// LMI_TEST(was_move_constructed_as_expected(u_C0303));
+ LMI_TEST(was_move_constructed_as_expected(u_C0404));
+ LMI_TEST(was_move_constructed_as_expected(u_C0505));
+ LMI_TEST(was_move_constructed_as_expected(u_C3030));
+
// Test hypothesis: f ?≡ Ma
A1111 v_A1111; v_A1111 = std::move(t_A1111);
C0000 v_C0000; v_C0000 = std::move(t_C0000);
C0101 v_C0101; v_C0101 = std::move(t_C0101);
-// C0202 v_C0202; v_C0202 = std::move(t_C0202); // protected
-// C0303 v_C0303; v_C0303 = std::move(t_C0303); // deleted
+// C0202 v_C0202; v_C0202 = std::move(t_C0202); // !f: protected
+// C0303 v_C0303; v_C0303 = std::move(t_C0303); // !f: deleted
C0404 v_C0404; v_C0404 = std::move(t_C0404);
-// C0505 v_C0505; v_C0505 = std::move(t_C0505); // implicitly deleted
+// C0505 v_C0505; v_C0505 = std::move(t_C0505); // !f: implicitly deleted
C3030 v_C3030; v_C3030 = std::move(t_C3030);
+ // Test hypothesis: h ?≡ Wa
+ LMI_TEST(was_move_assigned_as_expected(v_A1111));
+ LMI_TEST(was_move_assigned_as_expected(v_C0000));
+ LMI_TEST(was_move_assigned_as_expected(v_C0101));
+// LMI_TEST(was_move_assigned_as_expected(v_C0202));
+// LMI_TEST(was_move_assigned_as_expected(v_C0303));
+ LMI_TEST(was_move_assigned_as_expected(v_C0404));
+// LMI_TEST(was_move_assigned_as_expected(v_C0505));
+ LMI_TEST(was_move_assigned_as_expected(v_C3030));
+
stifle_unused_warning(t_C0202);
stifle_unused_warning(t_C0303);