From 03e7af8523e09db3fa2cd2171696a11e5d9d44f6 Mon Sep 17 00:00:00 2001
From: Christoph Lehmann <christoph.lehmann@ufz.de>
Date: Fri, 8 Jan 2016 15:54:51 +0100
Subject: [PATCH] [BL] const + mutable, move assignment

const + mutable enable use as temporary variables
move assignment complements move construction
---
 BaseLib/ConfigTreeNew-impl.h | 16 ++++----
 BaseLib/ConfigTreeNew.cpp    | 40 ++++++++++++------
 BaseLib/ConfigTreeNew.h      | 80 +++++++++++++++++++-----------------
 3 files changed, 78 insertions(+), 58 deletions(-)

diff --git a/BaseLib/ConfigTreeNew-impl.h b/BaseLib/ConfigTreeNew-impl.h
index 74c16dbf5fb..8fb48906aea 100644
--- a/BaseLib/ConfigTreeNew-impl.h
+++ b/BaseLib/ConfigTreeNew-impl.h
@@ -33,7 +33,7 @@ private:
 template<typename T>
 T
 ConfigTreeNew::
-getConfParam(std::string const& param)
+getConfParam(std::string const& param) const
 {
     auto p = getConfParamOptional<T>(param);
     if (p) return *p;
@@ -45,7 +45,7 @@ getConfParam(std::string const& param)
 template<typename T>
 T
 ConfigTreeNew::
-getConfParam(std::string const& param, T const& default_value)
+getConfParam(std::string const& param, T const& default_value) const
 {
     auto p = getConfParamOptional<T>(param);
     if (p) return *p;
@@ -55,7 +55,7 @@ getConfParam(std::string const& param, T const& default_value)
 template<typename T>
 boost::optional<T>
 ConfigTreeNew::
-getConfParamOptional(std::string const& param)
+getConfParamOptional(std::string const& param) const
 {
     checkUnique(param);
     auto p = _tree->get_child_optional(param);
@@ -79,7 +79,7 @@ getConfParamOptional(std::string const& param)
 template<typename T>
 Range<ConfigTreeNew::ValueIterator<T> >
 ConfigTreeNew::
-getConfParamList(std::string const& param)
+getConfParamList(std::string const& param) const
 {
     checkUnique(param);
     markVisited<T>(param, true);
@@ -93,7 +93,7 @@ getConfParamList(std::string const& param)
 template<typename T>
 T
 ConfigTreeNew::
-peekConfParam(std::string const& param)
+peekConfParam(std::string const& param) const
 {
     checkKeyname(param);
 
@@ -116,7 +116,7 @@ peekConfParam(std::string const& param)
 template<typename T>
 void
 ConfigTreeNew::
-checkConfParam(std::string const& param, T const& value)
+checkConfParam(std::string const& param, T const& value) const
 {
     if (getConfParam<T>(param) != value) {
         error("The value of key <" + param + "> is not the expected one.");
@@ -126,7 +126,7 @@ checkConfParam(std::string const& param, T const& value)
 template<typename Ch>
 void
 ConfigTreeNew::
-checkConfParam(std::string const& param, Ch const* value)
+checkConfParam(std::string const& param, Ch const* value) const
 {
     if (getConfParam<std::string>(param) != value) {
         error("The value of key <" + param + "> is not the expected one.");
@@ -137,7 +137,7 @@ checkConfParam(std::string const& param, Ch const* value)
 template<typename T>
 ConfigTreeNew::CountType&
 ConfigTreeNew::
-markVisited(std::string const& key, bool peek_only)
+markVisited(std::string const& key, bool peek_only) const
 {
     auto const type = std::type_index(typeid(T));
 
diff --git a/BaseLib/ConfigTreeNew.cpp b/BaseLib/ConfigTreeNew.cpp
index 956b7bf7fd9..0819b07574e 100644
--- a/BaseLib/ConfigTreeNew.cpp
+++ b/BaseLib/ConfigTreeNew.cpp
@@ -73,9 +73,25 @@ ConfigTreeNew::~ConfigTreeNew()
 	}
 }
 
+ConfigTreeNew&
+ConfigTreeNew::
+operator=(ConfigTreeNew&& other)
+{
+	_tree = other._tree;
+	other._tree = nullptr;
+	_path = other._path;
+	_visited_params = std::move(other._visited_params);
+
+	// TODO Caution: That might be a very nontrivial operation (copying a std::function).
+	_onerror = other._onerror;
+	_onwarning = other._onwarning;
+
+	return *this;
+}
+
 ConfigTreeNew
 ConfigTreeNew::
-getConfSubtree(std::string const& root)
+getConfSubtree(std::string const& root) const
 {
     if (auto t = getConfSubtreeOptional(root)) {
         return std::move(*t);
@@ -87,7 +103,7 @@ getConfSubtree(std::string const& root)
 
 boost::optional<ConfigTreeNew>
 ConfigTreeNew::
-getConfSubtreeOptional(std::string const& root)
+getConfSubtreeOptional(std::string const& root) const
 {
     checkUnique(root);
     auto subtree = _tree->get_child_optional(root);
@@ -104,7 +120,7 @@ getConfSubtreeOptional(std::string const& root)
 
 Range<ConfigTreeNew::SubtreeIterator>
 ConfigTreeNew::
-getConfSubtreeList(std::string const& root)
+getConfSubtreeList(std::string const& root) const
 {
     checkUnique(root);
     markVisited(root, true);
@@ -116,7 +132,7 @@ getConfSubtreeList(std::string const& root)
                 SubtreeIterator(p.second, root, *this));
 }
 
-void ConfigTreeNew::ignoreConfParam(const std::string &param)
+void ConfigTreeNew::ignoreConfParam(const std::string &param) const
 {
     checkUnique(param);
     // if not found, peek only
@@ -124,7 +140,7 @@ void ConfigTreeNew::ignoreConfParam(const std::string &param)
     markVisited(param, peek_only);
 }
 
-void ConfigTreeNew::ignoreConfParamAll(const std::string &param)
+void ConfigTreeNew::ignoreConfParamAll(const std::string &param) const
 {
     checkUnique(param);
     auto& ct = markVisited(param, true);
@@ -136,12 +152,12 @@ void ConfigTreeNew::ignoreConfParamAll(const std::string &param)
 }
 
 
-void ConfigTreeNew::error(const std::string& message)
+void ConfigTreeNew::error(const std::string& message) const
 {
 	_onerror(_path, message);
 }
 
-void ConfigTreeNew::warning(const std::string& message)
+void ConfigTreeNew::warning(const std::string& message) const
 {
 	_onwarning(_path, message);
 }
@@ -168,7 +184,7 @@ std::string ConfigTreeNew::shortString(const std::string &s)
 }
 
 
-void ConfigTreeNew::checkKeyname(std::string const& key)
+void ConfigTreeNew::checkKeyname(std::string const& key) const
 {
 	if (key.empty()) {
 		error("Search for empty key.");
@@ -180,7 +196,7 @@ void ConfigTreeNew::checkKeyname(std::string const& key)
 }
 
 std::string ConfigTreeNew::
-joinPaths( const std::string &p1, const std::string &p2)
+joinPaths( const std::string &p1, const std::string &p2) const
 {
 	if (p2.empty()) {
 		error("Second path to be joined is empty.");
@@ -191,7 +207,7 @@ joinPaths( const std::string &p1, const std::string &p2)
 	return p1 + pathseparator + p2;
 }
 
-void ConfigTreeNew::checkUnique(const std::string &key)
+void ConfigTreeNew::checkUnique(const std::string &key) const
 {
 	checkKeyname(key);
 
@@ -202,14 +218,14 @@ void ConfigTreeNew::checkUnique(const std::string &key)
 
 ConfigTreeNew::CountType&
 ConfigTreeNew::
-markVisited(std::string const& key, bool peek_only)
+markVisited(std::string const& key, bool peek_only) const
 {
     return markVisited<ConfigTreeNew>(key, peek_only);
 }
 
 void
 ConfigTreeNew::
-markVisitedDecrement(std::string const& key)
+markVisitedDecrement(std::string const& key) const
 {
     auto const type = std::type_index(typeid(nullptr));
 
diff --git a/BaseLib/ConfigTreeNew.h b/BaseLib/ConfigTreeNew.h
index 8623041e127..a14748733b2 100644
--- a/BaseLib/ConfigTreeNew.h
+++ b/BaseLib/ConfigTreeNew.h
@@ -62,7 +62,7 @@ public:
         using Iterator = boost::property_tree::ptree::const_assoc_iterator;
 
         explicit SubtreeIterator(Iterator it, std::string const& root,
-                                 ConfigTreeNew& parent)
+                                 ConfigTreeNew const& parent)
             : _it(it), _root(root), _parent(parent)
         {}
 
@@ -94,7 +94,7 @@ public:
         bool _has_incremented = true;
         Iterator _it;
         std::string const _root;
-        ConfigTreeNew& _parent;
+        ConfigTreeNew const& _parent;
     };
 
 
@@ -112,7 +112,7 @@ public:
         using Iterator = boost::property_tree::ptree::const_assoc_iterator;
 
         explicit ValueIterator(Iterator it, std::string const& root,
-                               ConfigTreeNew& parent)
+                               ConfigTreeNew const& parent)
             : _it(it), _root(root), _parent(parent)
         {}
 
@@ -156,7 +156,7 @@ public:
         bool _has_incremented = true;
         Iterator _it;
         std::string const _root;
-        ConfigTreeNew& _parent;
+        ConfigTreeNew const& _parent;
     };
 
     using PTree = boost::property_tree::ptree;
@@ -194,8 +194,12 @@ public:
 
     ConfigTreeNew() = delete;
 
-    void operator=(ConfigTreeNew const&) = delete;
-    void operator=(ConfigTreeNew &&) = delete;
+    //! copying is not compatible with the semantics of this class
+    ConfigTreeNew& operator=(ConfigTreeNew const&) = delete;
+
+    //! After being moved from, \c other is in an undefined state and must not be
+    //! used anymore!
+    ConfigTreeNew& operator=(ConfigTreeNew &&);
 
     /*! Get parameter \c param of type \c T from the configuration tree.
      *
@@ -206,7 +210,7 @@ public:
      * \pre \c param must not have been read before from this ConfigTree.
      */
     template<typename T> T
-    getConfParam(std::string const& param);
+    getConfParam(std::string const& param) const;
 
     /*! Get parameter \c param of type \c T from the configuration tree or the \c default_value.
      *
@@ -216,7 +220,7 @@ public:
      * \pre \c param must not have been read before from this ConfigTree.
      */
     template<typename T> T
-    getConfParam(std::string const& param, T const& default_value);
+    getConfParam(std::string const& param, T const& default_value) const;
 
     /*! Get parameter \c param of type \c T from the configuration tree if present
      *
@@ -227,7 +231,7 @@ public:
      * \pre \c param must not have been read before from this ConfigTree.
      */
     template<typename T> boost::optional<T>
-    getConfParamOptional(std::string const& param);
+    getConfParamOptional(std::string const& param) const;
 
     /*! Returns all parameters with the name \c param from the current level of the tree.
      *
@@ -236,7 +240,7 @@ public:
      * \pre \c param must not have been read before from this ConfigTree.
      */
     template<typename T> Range<ValueIterator<T> >
-    getConfParamList(std::string const& param);
+    getConfParamList(std::string const& param) const;
 
     /*! Peek at a parameter \c param of type \c T from the configuration tree.
      *
@@ -246,18 +250,18 @@ public:
      * Return value and error behaviour are the same as for getConfParam(std::string const&).
      */
     template<typename T> T
-    peekConfParam(std::string const& param);
+    peekConfParam(std::string const& param) const;
 
     /*! Assert that \c param has the given \c value.
      *
      * Convenience method combining getConfParam(std::string const&) with a check.
      */
     template<typename T> void
-    checkConfParam(std::string const& param, T const& value);
+    checkConfParam(std::string const& param, T const& value) const;
 
     //! Make checkConfParam() work for string literals.
     template<typename Ch> void
-    checkConfParam(std::string const& param, Ch const* value);
+    checkConfParam(std::string const& param, Ch const* value) const;
 
     /*! Get the subtree rooted at \c root
      *
@@ -266,14 +270,14 @@ public:
      * \pre \c root must not have been read before from this ConfigTree.
      */
     ConfigTreeNew
-    getConfSubtree(std::string const& root);
+    getConfSubtree(std::string const& root) const;
 
     /*! Get the subtree rooted at \c root if present
      *
      * \pre \c root must not have been read before from this ConfigTree.
      */
     boost::optional<ConfigTreeNew>
-    getConfSubtreeOptional(std::string const& root);
+    getConfSubtreeOptional(std::string const& root) const;
 
     /*! Get all subtrees that have a root \c root from the current level of the tree.
      *
@@ -282,7 +286,7 @@ public:
      * \pre \c root must not have been read before from this ConfigTree.
      */
     Range<SubtreeIterator>
-    getConfSubtreeList(std::string const& root);
+    getConfSubtreeList(std::string const& root) const;
 
     /*! Tell this instance to ignore parameter \c param.
      *
@@ -290,7 +294,7 @@ public:
      *
      * \pre \c root must not have been read before from this ConfigTree.
      */
-    void ignoreConfParam(std::string const& param);
+    void ignoreConfParam(std::string const& param) const;
 
     /*! Tell this instance to ignore all parameters \c param on the current level of the tree.
      *
@@ -298,12 +302,20 @@ public:
      *
      * \pre \c root must not have been read before from this ConfigTree.
      */
-    void ignoreConfParamAll(std::string const& param);
+    void ignoreConfParamAll(std::string const& param) const;
 
     //! The destructor performs the check if all nodes at the current level of the tree
     //! have been read.
     ~ConfigTreeNew();
 
+    //! Default error callback function
+    //! Will print an error message and call std::abort()
+    static void onerror(std::string const& path, std::string const& message);
+
+    //! Default warning callback function
+    //! Will print a warning message
+    static void onwarning(std::string const& path, std::string const& message);
+
 private:
     struct CountType
     {
@@ -316,20 +328,20 @@ private:
 
     //! Called if an error occurs. Will call the error callback.
     //! This method only acts as a helper method.
-    void error(std::string const& message);
+    void error(std::string const& message) const;
 
     //! Called for printing warning messages. Will call the warning callback.
     //! This method only acts as a helper method.
-    void warning(std::string const& message);
+    void warning(std::string const& message) const;
 
     //! Checks if \c key complies with the rules [a-z0-9_].
-    void checkKeyname(std::string const& key);
+    void checkKeyname(std::string const& key) const;
 
     //! Used to generate the path of a subtree.
-    std::string joinPaths(std::string const& p1, std::string const& p2);
+    std::string joinPaths(std::string const& p1, std::string const& p2) const;
 
     //! Asserts that the \c key has not been read yet.
-    void checkUnique(std::string const& key);
+    void checkUnique(std::string const& key) const;
 
     /*! Keeps track of the key \c key and its value type \c T.
      *
@@ -338,7 +350,7 @@ private:
      * \c param peek_only if true, do not change the read-count of the given key.
      */
     template<typename T>
-    CountType& markVisited(std::string const& key, bool peek_only = false);
+    CountType& markVisited(std::string const& key, bool peek_only = false) const;
 
     /*! Keeps track of the key \c key and its value type ConfigTree.
      *
@@ -346,19 +358,11 @@ private:
      *
      * \c param peek_only if true, do not change the read-count of the given key.
      */
-    CountType& markVisited(std::string const& key, bool peek_only = false);
+    CountType& markVisited(std::string const& key, bool peek_only = false) const;
 
     //! Used in the destructor to compute the difference between number of reads of a parameter
     //! and the number of times it exists in the ConfigTree
-    void markVisitedDecrement(std::string const& key);
-
-    //! Default error callback function
-    //! Will print an error message and call std::abort()
-    static void onerror(std::string const& path, std::string const& message);
-
-    //! Default warning callback function
-    //! Will print a warning message
-    static void onwarning(std::string const& path, std::string const& message);
+    void markVisitedDecrement(std::string const& key) const;
 
     //! returns a short string at suitable for error/warning messages
     static std::string shortString(std::string const& s);
@@ -367,14 +371,14 @@ private:
     boost::property_tree::ptree const* _tree;
 
     //! A path printed in error/warning messages.
-    std::string const _path;
+    std::string _path;
 
     //! A map key -> (count, type) keeping track which parameters have been read how often
     //! and which datatype they have.
-    std::map<std::string, CountType> _visited_params;
+    mutable std::map<std::string, CountType> _visited_params;
 
-    const Callback _onerror;
-    const Callback _onwarning;
+    Callback _onerror;
+    Callback _onwarning;
 
     //! Character separating two path components.
     static const char pathseparator;
-- 
GitLab