Author: mordante
Date: Sat Oct  4 23:42:20 2008
New Revision: 29884

URL: http://svn.gna.org/viewcvs/wesnoth?rev=29884&view=rev
Log:
Add a copy policy templates.

These will be used for the font::ttext class, for now the class needs move
semantics but that might change later. This change will be committed later.
Also added the unit tests for the policies.

Added:
    trunk/src/copy_policy.hpp   (with props)
    trunk/src/tests/test_policy.cpp   (with props)
Modified:
    trunk/src/CMakeLists.txt
    trunk/src/Makefile.am
    trunk/src/SConscript

Modified: trunk/src/CMakeLists.txt
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/CMakeLists.txt?rev=29884&r1=29883&r2=29884&view=diff
==============================================================================
--- trunk/src/CMakeLists.txt (original)
+++ trunk/src/CMakeLists.txt Sat Oct  4 23:42:20 2008
@@ -456,6 +456,7 @@
        tests/test_config_cache.cpp
        tests/test_formula_ai.cpp
        tests/test_network_worker.cpp
+    tests/test_policy.cpp
        tests/test_team.cpp
     tests/test_util.cpp
        tests/gui/test_save_dialog.cpp

Modified: trunk/src/Makefile.am
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/Makefile.am?rev=29884&r1=29883&r2=29884&view=diff
==============================================================================
--- trunk/src/Makefile.am (original)
+++ trunk/src/Makefile.am Sat Oct  4 23:42:20 2008
@@ -272,6 +272,7 @@
        tests/test_config_cache.cpp \
        tests/test_formula_ai.cpp \
     tests/test_network_worker.cpp \
+       tests/test_policy.cpp \
        tests/test_team.cpp \
        tests/test_util.cpp \
        tests/gui/test_save_dialog.cpp \

Modified: trunk/src/SConscript
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/SConscript?rev=29884&r1=29883&r2=29884&view=diff
==============================================================================
--- trunk/src/SConscript (original)
+++ trunk/src/SConscript Sat Oct  4 23:42:20 2008
@@ -354,6 +354,7 @@
     tests/main.cpp
     tests/test_formula_ai.cpp
     tests/test_network_worker.cpp
+    tests/test_policy.cpp
     tests/test_team.cpp
     tests/test_util.cpp
     tests/gui/test_drop_target.cpp

Added: trunk/src/copy_policy.hpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/copy_policy.hpp?rev=29884&view=auto
==============================================================================
--- trunk/src/copy_policy.hpp (added)
+++ trunk/src/copy_policy.hpp Sat Oct  4 23:42:20 2008
@@ -1,0 +1,156 @@
+/* $Id$ */
+/*
+   Copyright (C) 2008 by Mark de Wever <[EMAIL PROTECTED]>
+   Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2
+   or at your option any later version.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY.
+
+   See the COPYING file for more details.
+*/
+
+/**
+ * @file copy_policies.hpp.
+ * Defines the copy policies for classes.
+ *
+ * When a class can have multiple copy policies these templates can be used.
+ * When a class uses this class it should define its own copy constructor to do
+ * a shallow copy and call copy() afterwards. Also it should define a 
assignment
+ * 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.
+ */
+
+#ifndef COPY_POLICY_HPP_INCLUDED
+#define COPY_POLICY_HPP_INCLUDED
+
+#include <boost/static_assert.hpp>
+
+/** Set to 1 if you want debug output to std::cerr. */
+#define COPY_POLICY_DEBUG 0
+
+#if COPY_POLICY_DEBUG
+#include <iostream>
+#endif
+
+/** Contains various policies for policy based designs. */
+namespace policies {
+
+/** Utilities for the policies. */
+namespace utils {
+
+/** Gets the reference version of type T. */
+template <class T>
+class treference_type
+{
+       template<class U>
+       struct thelper
+       {
+               typedef U& type;
+       };
+       template<class U>
+       struct thelper<U&>
+       {
+               typedef U type;
+       };
+public:
+       typedef typename thelper<T>::type type;
+};
+
+} // namespace utils 
+
+/**
+ * Allow no copies.
+ *
+ * When a class never should be copyable boost::noncopyable is a better
+ * alternative (or just do it manually).
+ */
+template<class T>
+class tno_copy
+{
+public:
+       /** The type to use in the copy constructor and assignment operator. */
+       typedef const typename utils::treference_type<T>::type rhs_type;
+
+       void copy(rhs_type /*rhs*/) 
+       {
+               BOOST_STATIC_ASSERT(sizeof(T) == 0);
+       }
+};
+
+/**
+ * Makes a shallow copy.
+ *
+ * Since the subclass already does the shallow part we do nothing.
+ */
+template<class T>
+class tshallow_copy
+{
+public:
+       /** The type to use in the copy constructor and assignment operator. */
+       typedef const typename utils::treference_type<T>::type rhs_type;
+
+       void copy(rhs_type /*rhs*/) 
+       { 
+#if COPY_POLICY_DEBUG
+               std::cerr << __func__ << ".\n";
+#endif         
+       }
+};
+
+/**
+ * Makes a deep copy.
+ *
+ * The subclass must define a function void clone() which gets called to do
+ * the copying.
+ */
+template<class T>
+class tdeep_copy
+{
+public:
+       /** The type to use in the copy constructor and assignment operator. */
+       typedef const typename utils::treference_type<T>::type rhs_type;
+
+       void copy(rhs_type rhs) 
+       { 
+#if COPY_POLICY_DEBUG
+               std::cerr << __func__ << ".\n";
+#endif         
+               if(&rhs != this) {
+                       static_cast<typename 
utils::treference_type<T>::type>(*this).clone();                   
+               }
+       }
+};
+
+/**
+ * Makes a move copy.
+ *
+ * The shared resources are moved from the original class to the copy and
+ * thus the original object no longer owns them. The subclass must define a
+ * function void dispose() which should clear the resources.
+ */
+template<class T>
+class tmove_copy
+{
+public:
+       /** The type to use in the copy constructor and assignment operator. */
+       typedef typename utils::treference_type<T>::type rhs_type;
+
+       void copy(rhs_type rhs)
+       { 
+#if COPY_POLICY_DEBUG
+               std::cerr << __func__ << ".\n";
+#endif         
+               if(&rhs != this) {
+                       rhs.invalidate();
+               }
+       }
+};
+
+} // namespace policy
+
+#endif

Propchange: trunk/src/copy_policy.hpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: trunk/src/copy_policy.hpp
------------------------------------------------------------------------------
    svn:keywords = 'Author Date Id Revision'

Added: trunk/src/tests/test_policy.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/tests/test_policy.cpp?rev=29884&view=auto
==============================================================================
--- trunk/src/tests/test_policy.cpp (added)
+++ trunk/src/tests/test_policy.cpp Sat Oct  4 23:42:20 2008
@@ -1,0 +1,226 @@
+/* $Id$ */
+/*
+   Copyright (C) 2008 by Mark de Wever <[EMAIL PROTECTED]>
+   Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2
+   or at your option any later version.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY.
+
+   See the COPYING file for more details.
+*/
+
+#include "utils/test_support.hpp"
+
+#include "copy_policy.hpp"
+
+/** Set to 1 if you want debug output to std::cerr. */
+#define TEST_POLICY_DEBUG 0
+
+#if TEST_POLICY_DEBUG
+#include <iostream>
+#endif
+
+BOOST_AUTO_TEST_SUITE( policy )
+
+namespace {
+
+/** Class to test the copy policies. */
+template <template<class> class copy_policy >
+struct ttest : public copy_policy<ttest<copy_policy> >
+{
+       typedef copy_policy<ttest<copy_policy> > policy;
+       typedef typename ttest<copy_policy>::rhs_type rhs_type;
+
+       ttest()
+               : policy()
+               , copied_constructed_(false)
+               , assigned_(false)
+               , cloned_(false)
+               , invalidated_(false)
+       {
+#if TEST_POLICY_DEBUG
+               std::cerr << "Default constructor " << __func__ << ".\n";
+#endif
+       }
+
+       ttest(rhs_type rhs) 
+               : policy(rhs)
+               , copied_constructed_(true)
+               , assigned_(rhs.assigned_)
+               , cloned_(rhs.cloned_)
+               , invalidated_(rhs.invalidated_)
+       { 
+#if TEST_POLICY_DEBUG
+               std::cerr << "Copy constructor " << __func__ << ".\n";
+#endif
+               copy(rhs); 
+       }
+
+       ttest& operator=(rhs_type rhs) 
+       {
+#if TEST_POLICY_DEBUG
+               std::cerr << __func__ << ".\n";
+#endif
+               copied_constructed_ = rhs.copied_constructed_;
+               assigned_ = true;
+               cloned_ = rhs.cloned_;
+               invalidated_ = rhs.invalidated_;
+
+               copy(rhs);
+
+               return *this;
+       }
+
+       /** 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 copied_constructed_
+               , assigned_
+               , cloned_
+               , invalidated_
+               ;
+};
+
+// Not really required but doesn't hurt.
+#if TEST_POLICY_DEBUG
+template<template<class >class T>
+std::ostream& operator<<(std::ostream &s, const ttest<T>& test)
+{
+       s << "copied_constructed_ " << test.copied_constructed_
+               << " assigned_ " << test.assigned_
+               << " cloned_ " << test.cloned_
+               << " invalidated_ " << test.invalidated_
+               ;
+       
+       return s;
+}
+#endif
+
+/** Tests the copy constructor of the policy. */
+template<template<class >class T>
+void copy_test(const bool orig_invalidated, const bool copy_cloned)
+{
+#if TEST_POLICY_DEBUG
+       std::cerr << __func__ << ".\n";
+#endif
+
+       ttest<T> orig;
+       ttest<T> cpy(orig);
+
+#if TEST_POLICY_DEBUG
+       std::cerr << "orig " << orig
+               << "\ncopy " << cpy 
+               << ".\n";
+#endif
+
+       BOOST_REQUIRE_EQUAL(orig.copied_constructed_, false);
+       BOOST_REQUIRE_EQUAL(orig.assigned_, false);
+       BOOST_REQUIRE_EQUAL(orig.cloned_, false);
+       BOOST_REQUIRE_EQUAL(orig.invalidated_, orig_invalidated); 
+
+       BOOST_REQUIRE_EQUAL(cpy.copied_constructed_, true);
+       BOOST_REQUIRE_EQUAL(cpy.assigned_, false);
+       BOOST_REQUIRE_EQUAL(cpy.cloned_, copy_cloned);
+       BOOST_REQUIRE_EQUAL(cpy.invalidated_, false);
+}
+
+/** Tests the assignment operator of the policy. */
+template<template<class >class T>
+void assign_test(const bool orig_invalidated, const bool copy_cloned)
+{
+#if TEST_POLICY_DEBUG
+       std::cerr << __func__ << ".\n";
+#endif
+       ttest<T> orig;
+       ttest<T> cpy;
+
+       cpy = orig;
+
+#if TEST_POLICY_DEBUG
+       std::cerr << "orig " << orig
+               << "\ncopy " << cpy 
+               << ".\n";
+#endif
+
+       BOOST_REQUIRE_EQUAL(orig.copied_constructed_, false);
+       BOOST_REQUIRE_EQUAL(orig.assigned_, false);
+       BOOST_REQUIRE_EQUAL(orig.cloned_, false);
+       BOOST_REQUIRE_EQUAL(orig.invalidated_, orig_invalidated); 
+
+       BOOST_REQUIRE_EQUAL(cpy.copied_constructed_, false);
+       BOOST_REQUIRE_EQUAL(cpy.assigned_, true);
+       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<template<class >class T>
+void test(const bool orig_invalidated, const bool copy_cloned)
+{
+       copy_test<T>(orig_invalidated, copy_cloned);
+       assign_test<T>(orig_invalidated, copy_cloned);
+}
+
+} // namespace
+
+BOOST_AUTO_TEST_CASE( test_copy_policy )
+{
+/*
+ * 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.
+ *
+ * [1] http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.9
+ */
+#if 0
+       ttest<policies::tno_copy> orig;
+
+       // Might or might not compile.
+       ttest<policies::tno_copy> copy1(ttest<policies::tno_copy>());
+#if 0
+       // Must fail to compile.
+       ttest<policies::tno_copy> copy2(orig);
+
+       // Must fail to compile.
+       orig = orig;
+#endif 
+#endif
+
+#if TEST_POLICY_DEBUG
+       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);
+}
+
+/* vim: set ts=4 sw=4: */
+BOOST_AUTO_TEST_SUITE_END()

Propchange: trunk/src/tests/test_policy.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: trunk/src/tests/test_policy.cpp
------------------------------------------------------------------------------
    svn:keywords = 'Author Date Id Revision'


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

Reply via email to