[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] odd/move_semantics e83d0e1d 2/5: Modernize class unc
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] odd/move_semantics e83d0e1d 2/5: Modernize class uncopyable and its documentation |
Date: |
Wed, 20 Jul 2022 19:50:36 -0400 (EDT) |
branch: odd/move_semantics
commit e83d0e1d2f5a4e6fd08be45d03412159648db543
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>
Modernize class uncopyable and its documentation
---
uncopyable_lmi.hpp | 35 +++++++++++++++++++++++------------
1 file changed, 23 insertions(+), 12 deletions(-)
diff --git a/uncopyable_lmi.hpp b/uncopyable_lmi.hpp
index a3cc2667..33cdf7c4 100644
--- a/uncopyable_lmi.hpp
+++ b/uncopyable_lmi.hpp
@@ -26,14 +26,26 @@
/// Forbid compiler to generate copy and assignment functions.
///
+/// Historical note. A mixin class like this was widely used prior to
+/// C++11, when the best way to prevent copying was a trick: declare
+/// the copy members private and don't implement them (and encapsulate
+/// that trick in a base class). Since C++11, no trickery is required:
+/// unwanted special members can be declared as deleted. While this
+/// class itself should no longer be used, it is preserved because its
+/// refinements to the less sophisticated base class typically used
+/// before C++11 demonstrate a useful technique that guides the design
+/// of other classes. Accordingly, this modernized implementation
+/// sheds its historical roots and explicitly deletes unwanted special
+/// members, including move as well as copy members.
+///
/// This implementation is an original work. The idea of a mixin with
/// private copy and assignment members is very old and of uncertain
-/// provenance. The idea of making that mixin a template seems to have
+/// provenance. The idea of using CRTP for that mixin seems to have
/// been suggested first by Cacciola:
/// http://lists.boost.org/Archives/boost/2001/09/16912.php
/// http://lists.boost.org/Archives/boost/2001/09/17385.php
///
-/// This class is often seen in a non-template guise, but consider:
+/// This class was often seen in a non-CRTP guise, but consider:
///
/// class B0 : private Uncopyable {};
/// class B1 : private Uncopyable {};
@@ -72,21 +84,20 @@
/// second example above--though that's inefficient, as already noted.
/// It's also not ideal for documenting the derived class, because
/// 'virtual' belongs in the base classes:
-/// http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.9
+///
https://isocpp.org/wiki/faq/multiple-inheritance#virtual-inheritance-where
/// Adding a new class later, e.g.:
/// class E : private Uncopyable, public D {};
/// would require changing D's inheritance to virtual, yet D and E are
/// likely to be declared in different source files.
///
-/// The present class does requires a template parameter (which is
-/// reasonably constrained to name the class rendered uncopyable):
+/// The present class uses CRTP, making its use slightly more verbose:
///
/// class B0 : private uncopyable<B0> {};
/// class B1 : private uncopyable<B1> {};
/// class D : private uncopyable<D>, public B0, public B1 {};
///
-/// but its clarity and efficiency make it the least objectionable
-/// option.
+/// but clarity and efficiency are more important. Asserted
+/// precondition: the template parameter names the derived class.
namespace lmi
{
@@ -95,14 +106,14 @@ class uncopyable
{
protected:
uncopyable() = default;
+ uncopyable(uncopyable const&) = delete;
+ uncopyable(uncopyable&&) = delete;
+ uncopyable& operator=(uncopyable const&) = delete;
+ uncopyable& operator=(uncopyable&&) = delete;
~uncopyable()
{
- static_assert(std::is_base_of<uncopyable<T>,T>::value, "");
+ static_assert(std::is_base_of_v<uncopyable<T>,T>);
}
-
- private:
- uncopyable(uncopyable const&);
- uncopyable& operator=(uncopyable const&);
};
} // namespace lmi