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