Author: mordante
Date: Sun Oct  5 14:20:04 2008
New Revision: 29900

URL: http://svn.gna.org/viewcvs/wesnoth?rev=29900&view=rev
Log:
Add a way to add a copy policy to an existing class with minimal changes.

Modified:
    trunk/src/copy_policy.hpp
    trunk/src/tests/test_policy.cpp

Modified: trunk/src/copy_policy.hpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/copy_policy.hpp?rev=29900&r1=29899&r2=29900&view=diff
==============================================================================
--- trunk/src/copy_policy.hpp (original)
+++ trunk/src/copy_policy.hpp Sun Oct  5 14:20:04 2008
@@ -22,7 +22,12 @@
  * operator which does a shallow copy and then call copy() (copy() test for 
self
  * assignment, but the assignment operator can also do the test.
  *
- * See tests/test_policy.cpp for an example implementation of this policy.
+ * Another option is to use the tcopy_policy class, which uses the default
+ * constructor, copy constructor and assignment operator of the class. This way
+ * it can easily be added to an existing class without changes.
+ *
+ * See tests/test_policy.cpp for an example implementation of this policy, both
+ * the intrusive and non-intrusive version.
  */
 
 #ifndef COPY_POLICY_HPP_INCLUDED
@@ -151,6 +156,53 @@
        }
 };
 
+/**
+ * Helper class to add a policy to an existing class.
+ *
+ * This 
+ */
+template <
+       class base,
+       template<class> class copy_policy 
+>
+struct tcopy_policy : public base, public copy_policy<tcopy_policy<base, 
copy_policy> >
+{
+       typedef copy_policy<tcopy_policy<base, copy_policy> > policy;
+       typedef typename tcopy_policy<base, copy_policy>::rhs_type rhs_type;
+
+       tcopy_policy()
+               : base()
+               , policy()
+       {
+#if COPY_POLICY_DEBUG
+               std::cerr << "tcopy_policy: default constructor.\n";
+#endif
+       }
+
+       tcopy_policy(rhs_type rhs) 
+               : base(rhs)
+               , policy(rhs)
+       { 
+#if COPY_POLICY_DEBUG
+               std::cerr << "tcopy_policy: copy constructor.\n";
+#endif
+               copy(rhs); 
+       }
+
+       tcopy_policy& operator=(rhs_type rhs) 
+       {
+#if COPY_POLICY_DEBUG
+               std::cerr << "tcopy_policy: assignment operator.\n";
+#endif
+               static_cast<base>(*this) = rhs;
+               static_cast<policy>(*this) = rhs;
+
+               copy(rhs);
+
+               return *this;
+       }
+};
+
 } // namespace policy
 
 #endif

Modified: trunk/src/tests/test_policy.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/tests/test_policy.cpp?rev=29900&r1=29899&r2=29900&view=diff
==============================================================================
--- trunk/src/tests/test_policy.cpp (original)
+++ trunk/src/tests/test_policy.cpp Sun Oct  5 14:20:04 2008
@@ -16,6 +16,7 @@
 
 #include "copy_policy.hpp"
 
+
 /** Set to 1 if you want debug output to std::cerr. */
 #define TEST_POLICY_DEBUG 0
 
@@ -25,7 +26,8 @@
 
 BOOST_AUTO_TEST_SUITE( policy )
 
-namespace {
+
+namespace intrusive {
 
 /** Class to test the copy policies. */
 template <template<class> class copy_policy >
@@ -176,7 +178,129 @@
        assign_test<T>(orig_invalidated, copy_cloned);
 }
 
-} // namespace
+} // namespace intrusive
+
+namespace non_intrusive {
+
+struct ttest 
+{
+       ttest()
+               : cloned_(false)
+               , invalidated_(false)
+       {
+#if TEST_POLICY_DEBUG
+               std::cerr << "Default constructor " << __func__ << ".\n";
+#endif
+       }
+
+#if TEST_POLICY_DEBUG
+
+       ttest(const ttest& rhs) 
+               : cloned_(rhs.cloned_)
+               , invalidated_(rhs.invalidated_)
+       { 
+               std::cerr << "Copy constructor " << __func__ << ".\n";
+       }
+
+       ttest& operator=(const ttest& rhs) 
+       {
+               std::cerr << "Assign operator " << __func__ << ".\n";
+
+               cloned_ = rhs.cloned_;
+               invalidated_ = rhs.invalidated_;
+
+               return *this;
+       }
+#endif
+
+       /** Mandatory helper for the tmove_copy policy. */
+       void invalidate() { invalidated_ = true; }
+
+       /** Mandatory helper for the tdeep_copy policy. */
+       void clone() { cloned_ = true; }
+
+       /** A group helper variables  */
+       bool cloned_, invalidated_;
+};
+
+// Not really required but doesn't hurt.
+#if TEST_POLICY_DEBUG
+static std::ostream& operator<<(std::ostream &s, const ttest& test)
+{
+       s << "cloned_ " << test.cloned_
+               << " invalidated_ " << test.invalidated_
+               ;
+       
+       return s;
+}
+#endif
+
+/** Tests the copy constructor of the policy. */
+template<class T, template<class >class U>
+void copy_test(const bool orig_invalidated, const bool copy_cloned)
+{
+#if TEST_POLICY_DEBUG
+       std::cerr << __func__ << ".\n";
+#endif
+
+       policies::tcopy_policy<T, U> orig;
+       policies::tcopy_policy<T, U> cpy(orig);
+
+#if TEST_POLICY_DEBUG
+       std::cerr << "orig " << orig
+               << "\ncopy " << cpy 
+               << ".\n";
+#endif
+
+       BOOST_REQUIRE_EQUAL(orig.cloned_, false);
+       BOOST_REQUIRE_EQUAL(orig.invalidated_, orig_invalidated); 
+
+       BOOST_REQUIRE_EQUAL(cpy.cloned_, copy_cloned);
+       BOOST_REQUIRE_EQUAL(cpy.invalidated_, false);
+}
+
+/** Tests the assignment operator of the policy. */
+template<class T, template<class >class U>
+void assign_test(const bool orig_invalidated, const bool copy_cloned)
+{
+#if TEST_POLICY_DEBUG
+       std::cerr << __func__ << ".\n";
+#endif
+       policies::tcopy_policy<T, U> orig;
+       policies::tcopy_policy<T, U> cpy;
+
+       cpy = orig;
+
+#if TEST_POLICY_DEBUG
+       std::cerr << "orig " << orig
+               << "\ncopy " << cpy 
+               << ".\n";
+#endif
+
+       BOOST_REQUIRE_EQUAL(orig.cloned_, false);
+       BOOST_REQUIRE_EQUAL(orig.invalidated_, orig_invalidated); 
+
+       BOOST_REQUIRE_EQUAL(cpy.cloned_, copy_cloned);
+       BOOST_REQUIRE_EQUAL(cpy.invalidated_, false);
+}
+
+/** 
+ * Tests a policy.
+ *
+ * @param orig_invalidated        Should the original object be invalidated 
when
+ *                                used as rhs in an assignment or as parameter
+ *                                in a copy constructor.
+ * @param copy_cloned             Should the copy be cloned when use as lhs in
+ *                                an assignment or when being copy constructed.
+ */
+template<class T, template<class >class U>
+void test(const bool orig_invalidated, const bool copy_cloned)
+{
+       copy_test<T, U>(orig_invalidated, copy_cloned);
+       assign_test<T, U>(orig_invalidated, copy_cloned);
+}
+
+} // namespace non_intrusive
 
 BOOST_AUTO_TEST_CASE( test_copy_policy )
 {
@@ -184,18 +308,18 @@
  * The no copy policy shouldn't compile so it's commented out. The first part
  * enables the basics and can also test whether the compiler does a RVO [1],
  * if the compiler does the copy1 can be constructed. The second part should
- * always fail.
+ * always fail. (The non intrusive version is not added here.)
  *
  * [1] http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.9
  */
 #if 0
-       ttest<policies::tno_copy> orig;
+       intrusive::ttest<policies::tno_copy> orig;
 
        // Might or might not compile.
-       ttest<policies::tno_copy> copy1(ttest<policies::tno_copy>());
+       intrusive::ttest<policies::tno_copy> copy1(ttest<policies::tno_copy>());
 #if 0
        // Must fail to compile.
-       ttest<policies::tno_copy> copy2(orig);
+       intrusive::ttest<policies::tno_copy> copy2(orig);
 
        // Must fail to compile.
        orig = orig;
@@ -206,20 +330,40 @@
        std::cerr << std::boolalpha;
 #endif
 
-#if TEST_POLICY_DEBUG
-       std::cerr << "Test shallow copy\n";
-#endif
-       test<policies::tshallow_copy>(false, false);
-
-#if TEST_POLICY_DEBUG
-       std::cerr << "\n\nTest deep copy\n";
-#endif
-       test<policies::tdeep_copy>(false, true);
-
-#if TEST_POLICY_DEBUG
-       std::cerr << "\n\nTest move copy\n";
-#endif
-       test<policies::tmove_copy>(true, false);
+       /* Intrusive tests */
+
+#if TEST_POLICY_DEBUG
+       std::cerr << "Test intrusive shallow copy\n";
+#endif
+       intrusive::test<policies::tshallow_copy>(false, false);
+
+#if TEST_POLICY_DEBUG
+       std::cerr << "\n\nTest intrusive deep copy\n";
+#endif
+       intrusive::test<policies::tdeep_copy>(false, true);
+
+#if TEST_POLICY_DEBUG
+       std::cerr << "\n\nTest intrusive move copy\n";
+#endif
+       intrusive::test<policies::tmove_copy>(true, false);
+
+       /* Non-intrusive tests */
+
+#if TEST_POLICY_DEBUG
+       std::cerr << "Test non-intrusive shallow copy\n";
+#endif
+       non_intrusive::test<non_intrusive::ttest, 
policies::tshallow_copy>(false, false);
+
+#if TEST_POLICY_DEBUG
+       std::cerr << "\n\nTest non-intrusive deep copy\n";
+#endif
+       non_intrusive::test<non_intrusive::ttest, policies::tdeep_copy>(false, 
true);
+
+#if TEST_POLICY_DEBUG
+       std::cerr << "\n\nTest non-intrusive move copy\n";
+#endif
+       non_intrusive::test<non_intrusive::ttest, policies::tmove_copy>(true, 
false);
+
 }
 
 /* vim: set ts=4 sw=4: */


_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits

Reply via email to