You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2019/01/04 12:26:51 UTC

svn commit: r1850355 - in /subversion/trunk/subversion/bindings/cxx: include/svnxx/revision.hpp tests/test_revision.cpp

Author: brane
Date: Fri Jan  4 12:26:51 2019
New Revision: 1850355

URL: http://svn.apache.org/viewvc?rev=1850355&view=rev
Log:
Make the revision kind in SVN++ svn::revision explicitly immutable.

It's illogical to be able to even theoretically change the kind of a revision
object, so we make that restriction explicit by making the class member const.

[in subversion/bindings/cxx]
* include/svnxx/revision.hpp: Include <new> for placement-new.
  (revision::tag): Make this immutable.
  (revision::operator=): New; work around the kind tag's immutability by
   destroying the object and creating a new object in place.
* tests/test_revision.cpp
  (assignment): New test case.

Modified:
    subversion/trunk/subversion/bindings/cxx/include/svnxx/revision.hpp
    subversion/trunk/subversion/bindings/cxx/tests/test_revision.cpp

Modified: subversion/trunk/subversion/bindings/cxx/include/svnxx/revision.hpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/include/svnxx/revision.hpp?rev=1850355&r1=1850354&r2=1850355&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/cxx/include/svnxx/revision.hpp (original)
+++ subversion/trunk/subversion/bindings/cxx/include/svnxx/revision.hpp Fri Jan  4 12:26:51 2019
@@ -30,6 +30,7 @@
 
 #include <chrono>
 #include <cstdint>
+#include <new>
 
 #include "tristate.hpp"
 
@@ -126,6 +127,18 @@ public:
     {}
 
   /**
+   * @brief Assignment operator.
+   * Uses in-place destruction/construction to maintain the immutability
+   * of the revision kind.
+   */
+  revision& operator=(const revision& that)
+    {
+      this->~revision();
+      new(this) revision(that);
+      return *this;
+    }
+
+  /**
    * @brief Return the revision kind.
    */
   kind get_kind() const noexcept
@@ -161,7 +174,7 @@ public:
 private:
   // Even if we were using C++17, we wouldn't use std::variant because we
   // already maintain an explicit discriminator tag for the union.
-  kind tag;           // Union discriminator
+  const kind tag;     // Union discriminator
   union {
     number revnum;    // (tag == kind::number): revision number.
     time<usec> date;  // (tag == kind::date): microseconds from epoch.

Modified: subversion/trunk/subversion/bindings/cxx/tests/test_revision.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxx/tests/test_revision.cpp?rev=1850355&r1=1850354&r2=1850355&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/cxx/tests/test_revision.cpp (original)
+++ subversion/trunk/subversion/bindings/cxx/tests/test_revision.cpp Fri Jan  4 12:26:51 2019
@@ -130,6 +130,28 @@ BOOST_AUTO_TEST_CASE(postconditions_date
   BOOST_CHECK_THROW(r.get_number(), std::logic_error);
 }
 
+BOOST_AUTO_TEST_CASE(assignment)
+{
+  using kind = svn::revision::kind;
+  using clock = std::chrono::system_clock;
+  const auto timestamp = clock::now();
+
+  svn::revision r;
+  BOOST_TEST((r.get_kind() == kind::unspecified));
+
+  r = svn::revision(kind::previous);
+  BOOST_TEST((r.get_kind() == kind::previous));
+
+  r = svn::revision(svn::revnum(0));
+  BOOST_TEST((r.get_kind() == kind::number));
+  BOOST_TEST((r.get_number() == svn::revnum(0)));
+
+  r = svn::revision(timestamp);
+  BOOST_TEST((r.get_kind() == kind::date));
+  BOOST_TEST((r.get_date<clock::duration>() == timestamp));
+  BOOST_TEST((r.get_date<svn::revision::usec>() == timestamp));
+}
+
 // TODO: Add tests for !=, <, >, <= and >=
 
 BOOST_AUTO_TEST_SUITE_END();