lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] master cd3725d: Expunge 'obstruct_slicing'; use 'fin


From: Greg Chicares
Subject: [lmi-commits] [lmi] master cd3725d: Expunge 'obstruct_slicing'; use 'final' instead
Date: Thu, 2 Mar 2017 07:25:06 -0500 (EST)

branch: master
commit cd3725db8bc365c183d95ea988c7bb3bec918111
Author: Gregory W. Chicares <address@hidden>
Commit: Gregory W. Chicares <address@hidden>

    Expunge 'obstruct_slicing'; use 'final' instead
---
 Makefile.am                |   8 ---
 actuarial_table.hpp        |   6 +-
 antediluvian_stubs.cpp     |   6 +-
 any_member.hpp             |   9 +--
 authenticity.hpp           |   6 +-
 callback.hpp               |   6 +-
 census_view.hpp            |   8 +--
 commutation_functions.hpp  |  11 ++--
 configurable_settings.hpp  |  10 ++-
 database.hpp               |   6 +-
 database_view.hpp          |   8 +--
 dbdict.hpp                 |  12 ++--
 dbvalue.hpp                |   4 +-
 death_benefits.hpp         |   6 +-
 emit_ledger.hpp            |   6 +-
 fenv_guard.hpp             |   6 +-
 fund_data.hpp              |   9 +--
 global_settings.hpp        |   6 +-
 gpt_input.cpp              |   3 +-
 gpt_input.hpp              |  12 ++--
 gpt_server.hpp             |   4 +-
 gpt_state.cpp              |   3 +-
 gpt_state.hpp              |  10 ++-
 gpt_view.hpp               |   8 +--
 gpt_xml_document.hpp       |   6 +-
 group_values.hpp           |   4 +-
 ihs_irc7702.hpp            |   6 +-
 ihs_irc7702a.hpp           |   4 +-
 illustration_view.hpp      |   8 +--
 illustrator.hpp            |   4 +-
 input.cpp                  |   3 +-
 input.hpp                  |  12 ++--
 input_sequence.hpp         |   6 +-
 input_sequence_parser.hpp  |   6 +-
 ledger_text_formats.cpp    |  11 ++--
 ledgervalues.hpp           |   6 +-
 main_wx_test.cpp           |   7 +-
 mec_input.cpp              |   3 +-
 mec_input.hpp              |  12 ++--
 mec_server.hpp             |   4 +-
 mec_state.cpp              |   3 +-
 mec_state.hpp              |  10 ++-
 mec_view.hpp               |   8 +--
 mec_xml_document.hpp       |   6 +-
 msw_workarounds.hpp        |   6 +-
 multiple_cell_document.hpp |   6 +-
 mvc_controller.hpp         |   8 +--
 name_value_pairs.hpp       |   6 +-
 objects.make               |   6 --
 obstruct_slicing.hpp       | 102 ----------------------------
 obstruct_slicing_test.cpp  | 161 ---------------------------------------------
 outlay.hpp                 |   6 +-
 pchlist.hpp                |   1 -
 policy_view.hpp            |   8 +--
 preferences_model.hpp      |   6 +-
 premium_tax.hpp            |   6 +-
 product_data.hpp           |  13 ++--
 rate_table.cpp             |  10 ++-
 rate_table.hpp             |   7 +-
 rounding_rules.hpp         |  13 ++--
 rounding_view.hpp          |   8 +--
 rtti_lmi.hpp               |   5 +-
 single_cell_document.hpp   |   6 +-
 stratified_charges.cpp     |   3 +-
 stratified_charges.hpp     |  11 ++--
 test_coding_rules.cpp      |   6 +-
 text_view.hpp              |   8 +--
 tier_view.hpp              |   8 +--
 yare_input.hpp             |   4 +-
 69 files changed, 160 insertions(+), 566 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 53a9c67..a586dd2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -121,7 +121,6 @@ TESTS = \
     test_name_value_pairs \
     test_ncnnnpnn \
     test_numeric_io \
-    test_obstruct_slicing \
     test_path_utility \
     test_premium_tax \
     test_print_matrix \
@@ -865,12 +864,6 @@ test_numeric_io_SOURCES = \
   timer.cpp
 test_numeric_io_CXXFLAGS = $(AM_CXXFLAGS)
 
-test_obstruct_slicing_SOURCES = \
-  $(common_test_objects) \
-  obstruct_slicing_test.cpp \
-  timer.cpp
-test_obstruct_slicing_CXXFLAGS = $(AM_CXXFLAGS)
-
 test_path_utility_SOURCES = \
   $(common_test_objects) \
   calendar_date.cpp \
@@ -1223,7 +1216,6 @@ noinst_HEADERS = \
     null_stream.hpp \
     numeric_io_cast.hpp \
     numeric_io_traits.hpp \
-    obstruct_slicing.hpp \
     oecumenic_enumerations.hpp \
     outlay.hpp \
     path_utility.hpp \
diff --git a/actuarial_table.hpp b/actuarial_table.hpp
index 8527429..fd288b6 100644
--- a/actuarial_table.hpp
+++ b/actuarial_table.hpp
@@ -24,7 +24,6 @@
 
 #include "config.hpp"
 
-#include "obstruct_slicing.hpp"
 #include "uncopyable_lmi.hpp"
 
 #include <iosfwd>
@@ -128,9 +127,8 @@ enum e_actuarial_table_method
 /// has apparently chosen to leave them that way for backward
 /// compatibility.
 
-class actuarial_table
-    :        private lmi::uncopyable <actuarial_table>
-    ,virtual private obstruct_slicing<actuarial_table>
+class actuarial_table final
+    :private lmi::uncopyable <actuarial_table>
 {
   public:
     actuarial_table(std::string const& filename, int table_number);
diff --git a/antediluvian_stubs.cpp b/antediluvian_stubs.cpp
index 6736f70..c2d671a 100644
--- a/antediluvian_stubs.cpp
+++ b/antediluvian_stubs.cpp
@@ -61,8 +61,7 @@ template class xml_serializable<gpt_state>;
 gpt_state::gpt_state() = default;
 
 gpt_state::gpt_state(gpt_state const&)
-    :obstruct_slicing  <gpt_state>()
-    ,xml_serializable  <gpt_state>()
+    :xml_serializable  <gpt_state>()
     ,MemberSymbolTable <gpt_state>()
 {}
 
@@ -98,8 +97,7 @@ template class xml_serializable<mec_state>;
 mec_state::mec_state() = default;
 
 mec_state::mec_state(mec_state const&)
-    :obstruct_slicing  <mec_state>()
-    ,xml_serializable  <mec_state>()
+    :xml_serializable  <mec_state>()
     ,MemberSymbolTable <mec_state>()
 {}
 
diff --git a/any_member.hpp b/any_member.hpp
index b31283b..eaa0f7d 100644
--- a/any_member.hpp
+++ b/any_member.hpp
@@ -63,7 +63,6 @@
 #include "any_entity.hpp"
 
 #include "assert_lmi.hpp"
-#include "obstruct_slicing.hpp"
 #include "rtti_lmi.hpp"
 #include "uncopyable_lmi.hpp"
 #include "value_cast.hpp"
@@ -229,9 +228,8 @@ MemberType* member_cast(any_member<ClassType>&);
 struct any_member_test;
 
 template<typename ClassType>
-class any_member
-    :virtual private obstruct_slicing<any_member<ClassType> >
-    ,public any_entity
+class any_member final
+    :public any_entity
 {
     template<typename MemberType, typename CT>
     friend MemberType* exact_cast(any_member<CT>&);
@@ -280,8 +278,7 @@ any_member<ClassType>::any_member()
 
 template<typename ClassType>
 any_member<ClassType>::any_member(any_member const& other)
-    :obstruct_slicing<any_member<ClassType> >()
-    ,any_entity (other)
+    :any_entity (other)
     ,object_    (other.object_)
     ,content_   (other.content_ ? other.content_->clone() : nullptr)
 {}
diff --git a/authenticity.hpp b/authenticity.hpp
index ece0dec..5c1231f 100644
--- a/authenticity.hpp
+++ b/authenticity.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "calendar_date.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 
@@ -48,9 +47,8 @@ enum {md5len = 128 / CHAR_BIT};
 /// 'cached_date_' holds the most-recently-validated date, or a
 /// peremptorily-invalid default value of JDN zero.
 
-class Authenticity
-    :        private lmi::uncopyable <Authenticity>
-    ,virtual private obstruct_slicing<Authenticity>
+class Authenticity final
+    :private lmi::uncopyable <Authenticity>
 {
     friend class PasskeyTest;
 
diff --git a/callback.hpp b/callback.hpp
index 885e8ca..d55750a 100644
--- a/callback.hpp
+++ b/callback.hpp
@@ -24,7 +24,6 @@
 
 #include "config.hpp"
 
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 
@@ -96,9 +95,8 @@
 /// 'alert*.?pp'.
 
 template<typename FunctionPointer>
-class LMI_SO callback
-    :        private lmi::uncopyable <callback<FunctionPointer> >
-    ,virtual private obstruct_slicing<callback<FunctionPointer> >
+class LMI_SO callback final
+    :private lmi::uncopyable <callback<FunctionPointer> >
 {
     static_assert(std::is_pointer<FunctionPointer>::value, "");
     typedef typename std::remove_pointer<FunctionPointer>::type f_type;
diff --git a/census_view.hpp b/census_view.hpp
index 6621f5f..0e22a93 100644
--- a/census_view.hpp
+++ b/census_view.hpp
@@ -29,7 +29,6 @@
 #include "input.hpp"
 #include "ledger.hpp"
 #include "mc_enum_type_enums.hpp"       // enum mcenum_emission
-#include "obstruct_slicing.hpp"
 #include "oecumenic_enumerations.hpp"
 #include "uncopyable_lmi.hpp"
 
@@ -45,10 +44,9 @@ class CensusViewDataViewModel;
 class WXDLLIMPEXP_FWD_ADV wxDataViewEvent;
 class WXDLLIMPEXP_FWD_ADV wxDataViewCtrl;
 
-class CensusView
-    :        public  ViewEx
-    ,        private lmi::uncopyable <CensusView>
-    ,virtual private obstruct_slicing<CensusView>
+class CensusView final
+    :public  ViewEx
+    ,private lmi::uncopyable <CensusView>
 {
     friend class CensusDocument;
     friend class CensusViewDataViewModel;
diff --git a/commutation_functions.hpp b/commutation_functions.hpp
index 4fe45fb..9f9c82a 100644
--- a/commutation_functions.hpp
+++ b/commutation_functions.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "mc_enum_type_enums.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 
@@ -33,9 +32,8 @@
 
 /// Ordinary-life commutation functions.
 
-class LMI_SO OLCommFns
-    :        private lmi::uncopyable <OLCommFns>
-    ,virtual private obstruct_slicing<OLCommFns>
+class LMI_SO OLCommFns final
+    :private lmi::uncopyable <OLCommFns>
 {
   public:
     OLCommFns
@@ -80,9 +78,8 @@ class LMI_SO OLCommFns
 /// k-ly, for mode parameter k; 'm-' might seem more clearly to stand
 /// for "modal", but would too easily be taken as connoting "monthly".
 
-class LMI_SO ULCommFns
-    :        private lmi::uncopyable <ULCommFns>
-    ,virtual private obstruct_slicing<ULCommFns>
+class LMI_SO ULCommFns final
+    :private lmi::uncopyable <ULCommFns>
 {
   public:
     ULCommFns
diff --git a/configurable_settings.hpp b/configurable_settings.hpp
index 3ab93da..96f1f43 100644
--- a/configurable_settings.hpp
+++ b/configurable_settings.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "any_member.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 #include "xml_serializable.hpp"
@@ -43,11 +42,10 @@
 ///
 /// Data members are documented in their accessors' implementations.
 
-class LMI_SO configurable_settings
-    :        private lmi::uncopyable   <configurable_settings>
-    ,virtual private obstruct_slicing  <configurable_settings>
-    ,        public  xml_serializable  <configurable_settings>
-    ,        public  MemberSymbolTable <configurable_settings>
+class LMI_SO configurable_settings final
+    :private lmi::uncopyable   <configurable_settings>
+    ,public  xml_serializable  <configurable_settings>
+    ,public  MemberSymbolTable <configurable_settings>
 {
   public:
     static configurable_settings& instance();
diff --git a/database.hpp b/database.hpp
index 8691095..907c677 100644
--- a/database.hpp
+++ b/database.hpp
@@ -27,7 +27,6 @@
 #include "dbindex.hpp"
 #include "dbnames.hpp"                  // e_database_key
 #include "mc_enum_type_enums.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 
@@ -41,9 +40,8 @@ class yare_input;
 
 /// Database of product parameters.
 
-class LMI_SO product_database
-    :        private lmi::uncopyable <product_database>
-    ,virtual private obstruct_slicing<product_database>
+class LMI_SO product_database final
+    :private lmi::uncopyable <product_database>
 {
     friend class input_test;       // For test_product_database().
     friend class premium_tax_test; // For test_rates().
diff --git a/database_view.hpp b/database_view.hpp
index 588a736..6d414f7 100644
--- a/database_view.hpp
+++ b/database_view.hpp
@@ -26,7 +26,6 @@
 
 #include "product_editor.hpp"
 
-#include "obstruct_slicing.hpp"
 #include "uncopyable_lmi.hpp"
 
 #include <memory>                       // std::shared_ptr
@@ -35,10 +34,9 @@ class DatabaseDocument;
 class DatabaseTableAdapter;
 class WXDLLIMPEXP_FWD_CORE wxTreeEvent;
 
-class DatabaseView
-    :        public  TreeGridViewBase
-    ,        private lmi::uncopyable <DatabaseView>
-    ,virtual private obstruct_slicing<DatabaseView>
+class DatabaseView final
+    :public  TreeGridViewBase
+    ,private lmi::uncopyable <DatabaseView>
 {
   public:
     DatabaseView();
diff --git a/dbdict.hpp b/dbdict.hpp
index 802bed7..8db66e2 100644
--- a/dbdict.hpp
+++ b/dbdict.hpp
@@ -27,7 +27,6 @@
 #include "any_member.hpp"
 #include "cache_file_reads.hpp"
 #include "dbvalue.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 #include "xml_serializable.hpp"
@@ -36,12 +35,11 @@
 
 /// Cached product database.
 
-class LMI_SO DBDictionary
-    :        private lmi::uncopyable   <DBDictionary>
-    ,virtual private obstruct_slicing  <DBDictionary>
-    ,        public  xml_serializable  <DBDictionary>
-    ,        public  MemberSymbolTable <DBDictionary>
-    ,        public  cache_file_reads  <DBDictionary>
+class LMI_SO DBDictionary final
+    :private lmi::uncopyable   <DBDictionary>
+    ,public  xml_serializable  <DBDictionary>
+    ,public  MemberSymbolTable <DBDictionary>
+    ,public  cache_file_reads  <DBDictionary>
 {
     friend class DatabaseDocument;
     friend class input_test;        // For test_product_database().
diff --git a/dbvalue.hpp b/dbvalue.hpp
index 4059180..03a6d70 100644
--- a/dbvalue.hpp
+++ b/dbvalue.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "dbindex.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "xml_lmi_fwd.hpp"
 
@@ -54,8 +53,7 @@ namespace xml_serialize {template<typename T> struct xml_io;}
 ///
 /// Implicitly-declared special member functions do the right thing.
 
-class LMI_SO database_entity
-    :virtual private obstruct_slicing<database_entity>
+class LMI_SO database_entity final
 {
     friend struct xml_serialize::xml_io<database_entity>;
 
diff --git a/death_benefits.hpp b/death_benefits.hpp
index 43db21b..0136c7e 100644
--- a/death_benefits.hpp
+++ b/death_benefits.hpp
@@ -25,16 +25,14 @@
 #include "config.hpp"
 
 #include "mc_enum_type_enums.hpp"
-#include "obstruct_slicing.hpp"
 #include "uncopyable_lmi.hpp"
 
 #include <vector>
 
 class yare_input;
 
-class death_benefits
-    :        private lmi::uncopyable <death_benefits>
-    ,virtual private obstruct_slicing<death_benefits>
+class death_benefits final
+    :private lmi::uncopyable <death_benefits>
 {
   public:
     death_benefits(int, yare_input const&);
diff --git a/emit_ledger.hpp b/emit_ledger.hpp
index 52a4318..81ef027 100644
--- a/emit_ledger.hpp
+++ b/emit_ledger.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "mc_enum_type_enums.hpp"       // enum mcenum_emission
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 
@@ -41,9 +40,8 @@ class Ledger;
 /// Each member function (except the lightweight ctor and dtor)
 /// returns time spent, which is almost always wanted.
 
-class LMI_SO ledger_emitter
-    :        private lmi::uncopyable <ledger_emitter>
-    ,virtual private obstruct_slicing<ledger_emitter>
+class LMI_SO ledger_emitter final
+    :private lmi::uncopyable <ledger_emitter>
 {
   public:
     ledger_emitter(fs::path const& case_filepath, mcenum_emission emission);
diff --git a/fenv_guard.hpp b/fenv_guard.hpp
index c37652e..ea03435 100644
--- a/fenv_guard.hpp
+++ b/fenv_guard.hpp
@@ -24,7 +24,6 @@
 
 #include "config.hpp"
 
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 
@@ -39,9 +38,8 @@
 /// Intended use: instantiate on the stack at the beginning of any
 /// floating-point calculations that presume the invariant.
 
-class LMI_SO fenv_guard
-    :        private lmi::uncopyable <fenv_guard>
-    ,virtual private obstruct_slicing<fenv_guard>
+class LMI_SO fenv_guard final
+    :private lmi::uncopyable <fenv_guard>
 {
   public:
     fenv_guard();
diff --git a/fund_data.hpp b/fund_data.hpp
index e0bba86..4a30dca 100644
--- a/fund_data.hpp
+++ b/fund_data.hpp
@@ -24,7 +24,6 @@
 
 #include "config.hpp"
 
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 
@@ -35,8 +34,7 @@
 
 // Implicitly-declared special member functions do the right thing.
 
-class LMI_SO FundInfo
-    :virtual private obstruct_slicing<FundInfo>
+class LMI_SO FundInfo final
 {
     friend class FundData;
 
@@ -62,9 +60,8 @@ class LMI_SO FundInfo
     std::string gloss_;
 };
 
-class LMI_SO FundData
-    :        private lmi::uncopyable <FundData>
-    ,virtual private obstruct_slicing<FundData>
+class LMI_SO FundData final
+    :private lmi::uncopyable <FundData>
 {
   public:
     FundData(std::string const& a_Filename);
diff --git a/global_settings.hpp b/global_settings.hpp
index 43af2ba..0afb65f 100644
--- a/global_settings.hpp
+++ b/global_settings.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "calendar_date.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 
@@ -66,9 +65,8 @@
 /// store them e.g. in xml files, and because that enables 'set_'
 /// functions to validate their arguments.
 
-class LMI_SO global_settings
-    :        private lmi::uncopyable <global_settings>
-    ,virtual private obstruct_slicing<global_settings>
+class LMI_SO global_settings final
+    :private lmi::uncopyable <global_settings>
 {
   public:
     static global_settings& instance();
diff --git a/gpt_input.cpp b/gpt_input.cpp
index 4174a76..3f7f1f7 100644
--- a/gpt_input.cpp
+++ b/gpt_input.cpp
@@ -132,8 +132,7 @@ gpt_input::gpt_input()
 }
 
 gpt_input::gpt_input(gpt_input const& z)
-    :obstruct_slicing  <gpt_input>()
-    ,xml_serializable  <gpt_input>()
+    :xml_serializable  <gpt_input>()
     ,MvcModel                     ()
     ,MemberSymbolTable <gpt_input>()
 {
diff --git a/gpt_input.hpp b/gpt_input.hpp
index 172f9c9..42e6a1f 100644
--- a/gpt_input.hpp
+++ b/gpt_input.hpp
@@ -33,7 +33,6 @@
 #include "datum_string.hpp"
 #include "mc_enum.hpp"
 #include "mc_enum_types.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "tn_range.hpp"
 #include "tn_range_types.hpp"
@@ -70,12 +69,11 @@ class product_database;
 /// are just excess baggage that can be eliminated once the 7702A
 /// calculations are rewritten.
 
-class LMI_SO gpt_input
-    :virtual private obstruct_slicing           <gpt_input>
-    ,        public  xml_serializable           <gpt_input>
-    ,        public  MvcModel
-    ,        public  MemberSymbolTable          <gpt_input>
-    ,        private boost::equality_comparable <gpt_input>
+class LMI_SO gpt_input final
+    :public  xml_serializable           <gpt_input>
+    ,public  MvcModel
+    ,public  MemberSymbolTable          <gpt_input>
+    ,private boost::equality_comparable <gpt_input>
 {
     friend class Server7702;
 
diff --git a/gpt_server.hpp b/gpt_server.hpp
index f7b9ca2..add73e4 100644
--- a/gpt_server.hpp
+++ b/gpt_server.hpp
@@ -26,7 +26,6 @@
 
 #include "gpt_state.hpp"
 #include "mc_enum_type_enums.hpp"       // enum mcenum_emission
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 
 #include <boost/filesystem/path.hpp>
@@ -47,9 +46,8 @@ class gpt_input;
 ///
 /// Implicitly-declared special member functions do the right thing.
 
-class LMI_SO gpt_server
+class LMI_SO gpt_server final
     :public std::unary_function<fs::path const&, bool>
-    ,virtual private obstruct_slicing<gpt_server>
 {
   public:
     explicit gpt_server(mcenum_emission);
diff --git a/gpt_state.cpp b/gpt_state.cpp
index e22e9f1..a2a06cd 100644
--- a/gpt_state.cpp
+++ b/gpt_state.cpp
@@ -50,8 +50,7 @@ gpt_state::gpt_state()
 }
 
 gpt_state::gpt_state(gpt_state const& z)
-    :obstruct_slicing  <gpt_state>()
-    ,xml_serializable  <gpt_state>()
+    :xml_serializable  <gpt_state>()
     ,MemberSymbolTable <gpt_state>()
 {
     AscribeMembers();
diff --git a/gpt_state.hpp b/gpt_state.hpp
index 529df76..55383de 100644
--- a/gpt_state.hpp
+++ b/gpt_state.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "any_member.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "xml_serializable.hpp"
 
@@ -47,11 +46,10 @@
 /// in particular, when their names are used to nominate xml elements.
 /// 'A*_' is reserved in case it's wanted later--e.g., for arguments.
 
-class LMI_SO gpt_state
-    :virtual private obstruct_slicing           <gpt_state>
-    ,        public  xml_serializable           <gpt_state>
-    ,        public  MemberSymbolTable          <gpt_state>
-    ,        private boost::equality_comparable <gpt_state>
+class LMI_SO gpt_state final
+    :public  xml_serializable           <gpt_state>
+    ,public  MemberSymbolTable          <gpt_state>
+    ,private boost::equality_comparable <gpt_state>
 {
     friend class Irc7702A;
 
diff --git a/gpt_view.hpp b/gpt_view.hpp
index 9848e6a..f5cfd8e 100644
--- a/gpt_view.hpp
+++ b/gpt_view.hpp
@@ -27,7 +27,6 @@
 #include "mvc_view.hpp"
 #include "view_ex.hpp"
 
-#include "obstruct_slicing.hpp"
 #include "oecumenic_enumerations.hpp"
 #include "uncopyable_lmi.hpp"
 
@@ -60,10 +59,9 @@ class gpt_mvc_view
     char const* DoResourceFileName() const override;
 };
 
-class gpt_view
-    :        public  ViewEx
-    ,        private lmi::uncopyable <gpt_view>
-    ,virtual private obstruct_slicing<gpt_view>
+class gpt_view final
+    :public  ViewEx
+    ,private lmi::uncopyable <gpt_view>
 {
     friend class gpt_document;
 
diff --git a/gpt_xml_document.hpp b/gpt_xml_document.hpp
index 337aea5..d9bdcee 100644
--- a/gpt_xml_document.hpp
+++ b/gpt_xml_document.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "gpt_input.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 #include "xml_lmi_fwd.hpp"
@@ -33,9 +32,8 @@
 #include <iosfwd>
 #include <string>
 
-class LMI_SO gpt_xml_document
-    :        private lmi::uncopyable <gpt_xml_document>
-    ,virtual private obstruct_slicing<gpt_xml_document>
+class LMI_SO gpt_xml_document final
+    :private lmi::uncopyable <gpt_xml_document>
 {
     friend class gpt_document;
     friend class gpt_view;
diff --git a/group_values.hpp b/group_values.hpp
index 8eae242..77acfd7 100644
--- a/group_values.hpp
+++ b/group_values.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "mc_enum_type_enums.hpp"       // enum mcenum_emission
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 
 #include <boost/filesystem/path.hpp>
@@ -72,8 +71,7 @@ struct census_run_result
 ///
 /// Implicitly-declared special member functions do the right thing.
 
-class LMI_SO run_census
-    :virtual private obstruct_slicing<run_census>
+class LMI_SO run_census final
 {
   public:
     run_census();
diff --git a/ihs_irc7702.hpp b/ihs_irc7702.hpp
index 0e3a7e6..6c6fd3e 100644
--- a/ihs_irc7702.hpp
+++ b/ihs_irc7702.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "mc_enum_type_enums.hpp"
-#include "obstruct_slicing.hpp"
 #include "round_to.hpp"
 #include "uncopyable_lmi.hpp"
 
@@ -51,9 +50,8 @@ class ULCommFns;
 // as needed, being sure to round conservatively if at all. Unrounded
 // values are especially needed for the iterative specamt calculation.
 
-class Irc7702
-    :        private lmi::uncopyable <Irc7702>
-    ,virtual private obstruct_slicing<Irc7702>
+class Irc7702 final
+    :private lmi::uncopyable <Irc7702>
 {
     friend class FindSpecAmt;
     friend class gpt_specamt;
diff --git a/ihs_irc7702a.hpp b/ihs_irc7702a.hpp
index 319cc4c..b7e21b0 100644
--- a/ihs_irc7702a.hpp
+++ b/ihs_irc7702a.hpp
@@ -26,7 +26,6 @@
 
 #include "mc_enum_type_enums.hpp"
 #include "mec_state.hpp"
-#include "obstruct_slicing.hpp"
 #include "round_to.hpp"
 #include "so_attributes.hpp"
 
@@ -41,8 +40,7 @@ void LMI_SO TestIrc7702A();
 
 // Implicitly-declared special member functions do the right thing.
 
-class Irc7702A
-    :virtual private obstruct_slicing<Irc7702A>
+class Irc7702A final
 {
   public:
     enum e_death_benefit_definition {e_death_benefit_7702A, e_specamt_7702A};
diff --git a/illustration_view.hpp b/illustration_view.hpp
index e6e5e33..0b787a2 100644
--- a/illustration_view.hpp
+++ b/illustration_view.hpp
@@ -35,7 +35,6 @@
 #include "view_ex.hpp"
 
 #include "mc_enum_type_enums.hpp"       // enum mcenum_emission
-#include "obstruct_slicing.hpp"
 #include "oecumenic_enumerations.hpp"
 #include "uncopyable_lmi.hpp"
 
@@ -51,10 +50,9 @@ class WXDLLIMPEXP_FWD_CORE wxHtmlWindow;
 // TODO ?? Consider adding an input reference member. Here, it's used
 // only for edit and run; in the census view class, it's used widely.
 
-class IllustrationView
-    :        public  ViewEx
-    ,        private lmi::uncopyable <IllustrationView>
-    ,virtual private obstruct_slicing<IllustrationView>
+class IllustrationView final
+    :public  ViewEx
+    ,private lmi::uncopyable <IllustrationView>
 {
     friend class IllustrationDocument;
 
diff --git a/illustrator.hpp b/illustrator.hpp
index b890109..b97c07c 100644
--- a/illustrator.hpp
+++ b/illustrator.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "mc_enum_type_enums.hpp"       // enum mcenum_emission
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 
 #include <boost/filesystem/path.hpp>
@@ -41,9 +40,8 @@ class Ledger;
 ///
 /// Implicitly-declared special member functions do the right thing.
 
-class LMI_SO illustrator
+class LMI_SO illustrator final
     :public std::unary_function<fs::path const&, bool>
-    ,virtual private obstruct_slicing<illustrator>
 {
   public:
     explicit illustrator(mcenum_emission);
diff --git a/input.cpp b/input.cpp
index 69b7d73..5990fca 100644
--- a/input.cpp
+++ b/input.cpp
@@ -237,8 +237,7 @@ Input::Input()
 }
 
 Input::Input(Input const& z)
-    :obstruct_slicing  <Input>()
-    ,xml_serializable  <Input>()
+    :xml_serializable  <Input>()
     ,MvcModel                 ()
     ,MemberSymbolTable <Input>()
 {
diff --git a/input.hpp b/input.hpp
index 6868984..3b2b09e 100644
--- a/input.hpp
+++ b/input.hpp
@@ -33,7 +33,6 @@
 #include "datum_string.hpp"
 #include "mc_enum.hpp"
 #include "mc_enum_types.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "tn_range.hpp"
 #include "tn_range_types.hpp"
@@ -116,12 +115,11 @@ class product_database;
 /// strings (through base class template MemberSymbolTable), though;
 /// for them, readability overcomes the usual convention.
 
-class LMI_SO Input
-    :virtual private obstruct_slicing           <Input>
-    ,        public  xml_serializable           <Input>
-    ,        public  MvcModel
-    ,        public  MemberSymbolTable          <Input>
-    ,        private boost::equality_comparable <Input>
+class LMI_SO Input final
+    :public  xml_serializable           <Input>
+    ,public  MvcModel
+    ,public  MemberSymbolTable          <Input>
+    ,private boost::equality_comparable <Input>
 {
     friend class input_test;
     friend class yare_input;
diff --git a/input_sequence.hpp b/input_sequence.hpp
index 5fe62a5..94e2e8a 100644
--- a/input_sequence.hpp
+++ b/input_sequence.hpp
@@ -132,16 +132,14 @@
 #include "config.hpp"
 
 #include "input_sequence_interval.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 
 #include <string>
 #include <vector>
 
-class LMI_SO InputSequence
-    :        private lmi::uncopyable <InputSequence>
-    ,virtual private obstruct_slicing<InputSequence>
+class LMI_SO InputSequence final
+    :private lmi::uncopyable <InputSequence>
 {
     template<typename T>
     friend std::string canonicalized_input_sequence(std::vector<T> const&);
diff --git a/input_sequence_parser.hpp b/input_sequence_parser.hpp
index 4c92a03..a2603e4 100644
--- a/input_sequence_parser.hpp
+++ b/input_sequence_parser.hpp
@@ -27,7 +27,6 @@
 #include "config.hpp"
 
 #include "input_sequence_interval.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 
@@ -35,9 +34,8 @@
 #include <string>
 #include <vector>
 
-class SequenceParser
-    :        private lmi::uncopyable <SequenceParser>
-    ,virtual private obstruct_slicing<SequenceParser>
+class SequenceParser final
+    :private lmi::uncopyable <SequenceParser>
 {
   public:
     SequenceParser
diff --git a/ledger_text_formats.cpp b/ledger_text_formats.cpp
index 082de8f..27ff87b 100644
--- a/ledger_text_formats.cpp
+++ b/ledger_text_formats.cpp
@@ -37,7 +37,6 @@
 #include "map_lookup.hpp"
 #include "mc_enum_types_aux.hpp"        // is_subject_to_ill_reg()
 #include "miscellany.hpp"
-#include "obstruct_slicing.hpp"
 #include "uncopyable_lmi.hpp"
 #include "value_cast.hpp"
 
@@ -139,9 +138,8 @@ std::map<std::string,ledger_metadata> const& 
ledger_metadata_map()
     return m;
 }
 
-class calculation_summary_formatter
-    :        private lmi::uncopyable <calculation_summary_formatter>
-    ,virtual private obstruct_slicing<calculation_summary_formatter>
+class calculation_summary_formatter final
+    :private lmi::uncopyable <calculation_summary_formatter>
 {
   public:
     calculation_summary_formatter(Ledger const&);
@@ -837,9 +835,8 @@ void PrintRosterTabDelimited
         }
 }
 
-class FlatTextLedgerPrinter
-    :        private lmi::uncopyable <FlatTextLedgerPrinter>
-    ,virtual private obstruct_slicing<FlatTextLedgerPrinter>
+class FlatTextLedgerPrinter final
+    :private lmi::uncopyable <FlatTextLedgerPrinter>
 {
   public:
     FlatTextLedgerPrinter(Ledger const&, std::ostream&);
diff --git a/ledgervalues.hpp b/ledgervalues.hpp
index 2dbecb4..12f4740 100644
--- a/ledgervalues.hpp
+++ b/ledgervalues.hpp
@@ -24,7 +24,6 @@
 
 #include "config.hpp"
 
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 
@@ -38,9 +37,8 @@ class Ledger;
 ///
 /// This class encapsulates a frequently-used series of operations.
 
-class IllusVal
-    :        private lmi::uncopyable <IllusVal>
-    ,virtual private obstruct_slicing<IllusVal>
+class IllusVal final
+    :private lmi::uncopyable <IllusVal>
 {
   public:
     explicit IllusVal(std::string const& filename);
diff --git a/main_wx_test.cpp b/main_wx_test.cpp
index 6fa8593..c746f0a 100644
--- a/main_wx_test.cpp
+++ b/main_wx_test.cpp
@@ -27,7 +27,6 @@
 #include "force_linking.hpp"
 #include "handle_exceptions.hpp"        // stealth_exception
 #include "main_common.hpp"              // initialize_application()
-#include "obstruct_slicing.hpp"
 #include "path_utility.hpp"             // initialize_filesystem()
 #include "skeleton.hpp"
 #include "uncopyable_lmi.hpp"
@@ -149,9 +148,9 @@ struct TestsResults
 /// Run the tests.
 ///
 /// This is a simple Meyers singleton.
-class application_test
-    :        private lmi::uncopyable  <application_test>
-    ,virtual private obstruct_slicing <application_test>
+
+class application_test final
+    :private lmi::uncopyable  <application_test>
 {
   public:
     static application_test& instance();
diff --git a/mec_input.cpp b/mec_input.cpp
index 09d2db7..917e395 100644
--- a/mec_input.cpp
+++ b/mec_input.cpp
@@ -122,8 +122,7 @@ mec_input::mec_input()
 }
 
 mec_input::mec_input(mec_input const& z)
-    :obstruct_slicing  <mec_input>()
-    ,xml_serializable  <mec_input>()
+    :xml_serializable  <mec_input>()
     ,MvcModel                     ()
     ,MemberSymbolTable <mec_input>()
 {
diff --git a/mec_input.hpp b/mec_input.hpp
index 3557dc3..041b6da 100644
--- a/mec_input.hpp
+++ b/mec_input.hpp
@@ -33,7 +33,6 @@
 #include "datum_string.hpp"
 #include "mc_enum.hpp"
 #include "mc_enum_types.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "tn_range.hpp"
 #include "tn_range_types.hpp"
@@ -63,12 +62,11 @@ class product_database;
 /// are just excess baggage that can be eliminated once the 7702A
 /// calculations are rewritten.
 
-class LMI_SO mec_input
-    :virtual private obstruct_slicing           <mec_input>
-    ,        public  xml_serializable           <mec_input>
-    ,        public  MvcModel
-    ,        public  MemberSymbolTable          <mec_input>
-    ,        private boost::equality_comparable <mec_input>
+class LMI_SO mec_input final
+    :public  xml_serializable           <mec_input>
+    ,public  MvcModel
+    ,public  MemberSymbolTable          <mec_input>
+    ,private boost::equality_comparable <mec_input>
 {
   public:
     mec_input();
diff --git a/mec_server.hpp b/mec_server.hpp
index b82e4db..f9382e0 100644
--- a/mec_server.hpp
+++ b/mec_server.hpp
@@ -26,7 +26,6 @@
 
 #include "mc_enum_type_enums.hpp"       // enum mcenum_emission
 #include "mec_state.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 
 #include <boost/filesystem/path.hpp>
@@ -47,9 +46,8 @@ class mec_input;
 ///
 /// Implicitly-declared special member functions do the right thing.
 
-class LMI_SO mec_server
+class LMI_SO mec_server final
     :public std::unary_function<fs::path const&, bool>
-    ,virtual private obstruct_slicing<mec_server>
 {
   public:
     explicit mec_server(mcenum_emission);
diff --git a/mec_state.cpp b/mec_state.cpp
index 7c06b66..fd0b3be 100644
--- a/mec_state.cpp
+++ b/mec_state.cpp
@@ -50,8 +50,7 @@ mec_state::mec_state()
 }
 
 mec_state::mec_state(mec_state const& z)
-    :obstruct_slicing  <mec_state>()
-    ,xml_serializable  <mec_state>()
+    :xml_serializable  <mec_state>()
     ,MemberSymbolTable <mec_state>()
 {
     AscribeMembers();
diff --git a/mec_state.hpp b/mec_state.hpp
index 47d14bb..4b24614 100644
--- a/mec_state.hpp
+++ b/mec_state.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "any_member.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "xml_serializable.hpp"
 
@@ -43,11 +42,10 @@
 /// in particular, when their names are used to nominate xml elements.
 /// 'A*_' is reserved in case it's wanted later--e.g., for arguments.
 
-class LMI_SO mec_state
-    :virtual private obstruct_slicing           <mec_state>
-    ,        public  xml_serializable           <mec_state>
-    ,        public  MemberSymbolTable          <mec_state>
-    ,        private boost::equality_comparable <mec_state>
+class LMI_SO mec_state final
+    :public  xml_serializable           <mec_state>
+    ,public  MemberSymbolTable          <mec_state>
+    ,private boost::equality_comparable <mec_state>
 {
     friend class Irc7702A;
 
diff --git a/mec_view.hpp b/mec_view.hpp
index 5591205..aa67056 100644
--- a/mec_view.hpp
+++ b/mec_view.hpp
@@ -27,7 +27,6 @@
 #include "mvc_view.hpp"
 #include "view_ex.hpp"
 
-#include "obstruct_slicing.hpp"
 #include "oecumenic_enumerations.hpp"
 #include "uncopyable_lmi.hpp"
 
@@ -60,10 +59,9 @@ class mec_mvc_view
     char const* DoResourceFileName() const override;
 };
 
-class mec_view
-    :        public  ViewEx
-    ,        private lmi::uncopyable <mec_view>
-    ,virtual private obstruct_slicing<mec_view>
+class mec_view final
+    :public  ViewEx
+    ,private lmi::uncopyable <mec_view>
 {
     friend class mec_document;
 
diff --git a/mec_xml_document.hpp b/mec_xml_document.hpp
index bd0488f..abfbc1c 100644
--- a/mec_xml_document.hpp
+++ b/mec_xml_document.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "mec_input.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 #include "xml_lmi_fwd.hpp"
@@ -33,9 +32,8 @@
 #include <iosfwd>
 #include <string>
 
-class LMI_SO mec_xml_document
-    :        private lmi::uncopyable <mec_xml_document>
-    ,virtual private obstruct_slicing<mec_xml_document>
+class LMI_SO mec_xml_document final
+    :private lmi::uncopyable <mec_xml_document>
 {
     friend class mec_document;
     friend class mec_view;
diff --git a/msw_workarounds.hpp b/msw_workarounds.hpp
index d867616..034495b 100644
--- a/msw_workarounds.hpp
+++ b/msw_workarounds.hpp
@@ -26,7 +26,6 @@
 
 #ifdef LMI_MSW
 
-#include "obstruct_slicing.hpp"
 #include "uncopyable_lmi.hpp"
 
 #include <deque>
@@ -49,9 +48,8 @@
 /// which they were loaded. The data member is of type std::deque
 /// in order to let this reversal be expressed more cleanly.
 
-class MswDllPreloader
-    :        private lmi::uncopyable <MswDllPreloader>
-    ,virtual private obstruct_slicing<MswDllPreloader>
+class MswDllPreloader final
+    :private lmi::uncopyable <MswDllPreloader>
 {
   public:
     static MswDllPreloader& instance();
diff --git a/multiple_cell_document.hpp b/multiple_cell_document.hpp
index 76043c1..3848ccf 100644
--- a/multiple_cell_document.hpp
+++ b/multiple_cell_document.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "input.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 #include "xml_lmi_fwd.hpp"
@@ -77,9 +76,8 @@
 /// add a new cell copied from a selection of class defaults, although
 /// that could of course be implemented.
 
-class LMI_SO multiple_cell_document
-    :        private lmi::uncopyable <multiple_cell_document>
-    ,virtual private obstruct_slicing<multiple_cell_document>
+class LMI_SO multiple_cell_document final
+    :private lmi::uncopyable <multiple_cell_document>
 {
 // TODO ?? Avoid long-distance friendship...in single-cell class, too.
     friend class CensusDocument;
diff --git a/mvc_controller.hpp b/mvc_controller.hpp
index 828b203..9998161 100644
--- a/mvc_controller.hpp
+++ b/mvc_controller.hpp
@@ -24,7 +24,6 @@
 
 #include "config.hpp"
 
-#include "obstruct_slicing.hpp"
 #include "uncopyable_lmi.hpp"
 
 #include <wx/bookctrl.h>                // wxBookCtrlBase, wxBookCtrlBaseEvent
@@ -405,10 +404,9 @@ namespace model_view_controller{} // doxygen workaround.
 /// unit_test_under_way_: True iff a unit test is in charge of the
 /// Controller.
 
-class MvcController
-    :        public  wxDialog
-    ,        private lmi::uncopyable <MvcController>
-    ,virtual private obstruct_slicing<MvcController>
+class MvcController final
+    :public  wxDialog
+    ,private lmi::uncopyable <MvcController>
 {
     friend class MvcTest;
 
diff --git a/name_value_pairs.hpp b/name_value_pairs.hpp
index 3feb1cd..729309a 100644
--- a/name_value_pairs.hpp
+++ b/name_value_pairs.hpp
@@ -24,7 +24,6 @@
 
 #include "config.hpp"
 
-#include "obstruct_slicing.hpp"
 #include "uncopyable_lmi.hpp"
 
 #include <map>
@@ -82,9 +81,8 @@
 /// purpose library, but it meets lmi's specialized needs, and such
 /// extra checks can easily be added if they become desirable.
 
-class name_value_pairs
-    :        private lmi::uncopyable <name_value_pairs>
-    ,virtual private obstruct_slicing<name_value_pairs>
+class name_value_pairs final
+    :private lmi::uncopyable <name_value_pairs>
 {
     friend int test_main(int, char*[]);
 
diff --git a/objects.make b/objects.make
index 9d980d5..9eaa9ff 100644
--- a/objects.make
+++ b/objects.make
@@ -432,7 +432,6 @@ unit_test_targets := \
   name_value_pairs_test \
   ncnnnpnn_test \
   numeric_io_test \
-  obstruct_slicing_test \
   path_utility_test \
   premium_tax_test \
   print_matrix_test \
@@ -765,11 +764,6 @@ numeric_io_test$(EXEEXT): \
   numeric_io_test.o \
   timer.o \
 
-obstruct_slicing_test$(EXEEXT): \
-  $(common_test_objects) \
-  obstruct_slicing_test.o \
-  timer.o \
-
 path_utility_test$(EXEEXT): \
   $(boost_filesystem_objects) \
   $(common_test_objects) \
diff --git a/obstruct_slicing.hpp b/obstruct_slicing.hpp
deleted file mode 100644
index 65eb471..0000000
--- a/obstruct_slicing.hpp
+++ /dev/null
@@ -1,102 +0,0 @@
-// Obstruct slicing.
-//
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 
2015, 2016, 2017 Gregory W. Chicares.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License version 2 as
-// published by the Free Software Foundation.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
-//
-// http://savannah.nongnu.org/projects/lmi
-// email: <address@hidden>
-// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
-
-#ifndef obstruct_slicing_hpp
-#define obstruct_slicing_hpp
-
-#include "config.hpp"
-
-/// Is it desirable to "prevent derivation" from a class? Some say
-/// the lack of a virtual destructor is a warning that any competent
-/// C++ programmer would consider thoughtfully; others, that feasible
-/// safeguards ought to be used where there might be any danger.
-///
-/// One purpose of such a safeguard is to prevent slicing. It may also
-/// be useful, for instance, for proving that it's safe to revise a
-/// legacy class that appears not to need a virtual dtor, but has one
-/// anyway, perhaps because of an obsolete "make all dtors virtual"
-/// guideline. After such a proof, it could be removed if wanted, but
-/// the accompanying unit test shows little runtime cost. It is vain
-/// to think that this safeguard would make virtual function calls
-/// faster: its purpose is safety, not efficiency.
-///
-/// Three techniques are discussed here, and one is exposed for use.
-/// None literally prevents derivation, but all create obstacles to
-/// instantiating a derived class.
-///
-/// 1. Probably the simplest technique is private virtual derivation
-/// from a utility class with a protected constructor:
-///
-/// class no_derive{ protected: no_derive0() {} };
-/// class A0 :private virtual no_derive0 {};
-/// class A1 :public A0 {};
-///
-/// That's too simplistic. The utility class should have a protected
-/// copy ctor as well, of course. Worse, two classes in the same
-/// inheritance hierarchy might derive from the same utility class,
-/// defeating its purpose:
-///
-/// class A1 :public A0, private virtual no_derive0 {};
-///
-/// That may seem like fraud, but could happen accidentally.
-///
-/// 2. The problems noted for the first technique may be solved thus:
-///
-/// template<typename T>
-/// class no_derive1
-/// {
-///   protected:
-///     no_derive1() {}
-///     no_derive1(no_derive1 const&) {}
-/// };
-///
-/// class B0: private virtual no_derive1<B0> {};
-///
-/// class B1: public B0, private virtual no_derive1<B1> {};
-///
-/// Specializing the utility class on the class to be protected makes
-/// it difficult to subvert the mechanism accidentally, because that
-/// would require code like
-///
-/// class B1: public B0, private virtual no_derive1<B0> {};
-///
-/// which is less likely to go unnoticed. And this technique permits
-/// protecting classes that are related by inheritance.
-///
-/// 3. It seems impossible to subvert the technique described here:
-///   http://www.research.att.com/~bs/bs_faq2.html#no-derivation
-/// but that is inconveniently verbose. It cannot be simplified by
-/// making the utility class a template. No single macro would work,
-/// and a pair of macros would be ugly.
-///
-/// The second technique seems terse and effective enough to be
-/// useful, and is therefore exposed here.
-
-template<typename T>
-class obstruct_slicing
-{
-  protected:
-    obstruct_slicing() = default;
-    obstruct_slicing(obstruct_slicing const&) = default;
-};
-
-#endif // obstruct_slicing_hpp
-
diff --git a/obstruct_slicing_test.cpp b/obstruct_slicing_test.cpp
deleted file mode 100644
index 39827be..0000000
--- a/obstruct_slicing_test.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-// Obstruct slicing.
-//
-// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 
2015, 2016, 2017 Gregory W. Chicares.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License version 2 as
-// published by the Free Software Foundation.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software Foundation,
-// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
-//
-// http://savannah.nongnu.org/projects/lmi
-// email: <address@hidden>
-// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
-
-#include "pchfile.hpp"
-
-#include "obstruct_slicing.hpp"
-
-#include "test_tools.hpp"
-#include "timer.hpp"
-
-#include <functional>                   // std::bind()
-#include <string>
-
-// Here are all the techniques discussed in the header.
-
-// Technique 1.
-
-class no_derive0
-{
-  protected:
-    no_derive0() = default;
-};
-
-class A0
-    :private virtual no_derive0
-{};
-
-class A1
-    :public A0
-    ,private virtual no_derive0 // Could be accident rather than fraud.
-{};
-
-// Technique 2.
-
-template<typename T>
-class no_derive1
-{
-  protected:
-    no_derive1() = default;
-    no_derive1(no_derive1 const&) = default;
-};
-
-class B0
-    :private virtual no_derive1<B0>
-{};
-
-class B1
-    :public B0
-    ,private virtual no_derive1<B1>
-//    ,private virtual no_derive1<B0> // Either fraud, or really careless.
-{};
-
-// Technique 3.
-
-class C0;
-
-class C0_no_derive
-{
-    friend class C0;
-
-  private:
-    C0_no_derive() = default;
-    C0_no_derive(C0_no_derive const&) = default;
-};
-
-class C0
-    :public virtual C0_no_derive
-{};
-
-class C1
-    :public C0
-    ,public virtual C0_no_derive
-{};
-
-void test_all_techniques()
-{
-// Technique 1.
-    A0 a0;
-    A1 a1;     // This is allowed, but an error was desired.
-    A1 a2(a1); // This is allowed, but an error was desired.
-
-// Technique 2.
-    B0 b0;
-//    B1 b1;     // Error, as desired.
-//    B1 b2(b1); // Error, as desired.
-
-// Technique 3.
-    C0 c0;
-//    C1 c1;     // Error, as desired.
-//    C1 c2(c1); // Error, as desired.
-}
-
-struct X0
-{
-    X0(): i(4), s("This is a test.") {}
-    void foo();
-    int i;
-    std::string s;
-};
-
-struct X1
-    :virtual private obstruct_slicing<X1>
-{
-    X1(): i(4), s("This is a test.") {}
-    void foo();
-    int i;
-    std::string s;
-};
-
-template<typename T>
-void mete(volatile int vi)
-{
-    T t0;
-    T t1(t0);
-    t0.i = vi;
-    t0 = t1;
-    vi = t1.i;
-}
-
-template<typename T>
-void test_cost_of_obstruction(std::string const& s)
-{
-    std::cout
-        << "  Class " << s << " has size " << sizeof(T) << '\n'
-        << "  Speed test: \n      "
-        << TimeAnAliquot(std::bind(mete<T>, 0))
-        << '\n'
-        ;
-}
-
-int test_main(int, char*[])
-{
-    test_all_techniques();
-
-    // Correctness is verifiable only at compile time. At run time,
-    // there's nothing to test except the cost.
-
-    test_cost_of_obstruction<X0>("X0");
-    test_cost_of_obstruction<X1>("X1");
-
-    return EXIT_SUCCESS;
-}
-
diff --git a/outlay.hpp b/outlay.hpp
index e304a69..ddc4a33 100644
--- a/outlay.hpp
+++ b/outlay.hpp
@@ -25,16 +25,14 @@
 #include "config.hpp"
 
 #include "mc_enum_type_enums.hpp"
-#include "obstruct_slicing.hpp"
 #include "uncopyable_lmi.hpp"
 
 #include <vector>
 
 class yare_input;
 
-class modal_outlay
-    :        private lmi::uncopyable <modal_outlay>
-    ,virtual private obstruct_slicing<modal_outlay>
+class modal_outlay final
+    :private lmi::uncopyable <modal_outlay>
 {
     friend class AccountValue;
 
diff --git a/pchlist.hpp b/pchlist.hpp
index b15a4cc..bfd7d47 100644
--- a/pchlist.hpp
+++ b/pchlist.hpp
@@ -77,7 +77,6 @@
 #   include "null_stream.hpp"
 #   include "numeric_io_cast.hpp"
 #   include "numeric_io_traits.hpp"
-#   include "obstruct_slicing.hpp"
 #   include "oecumenic_enumerations.hpp"
 #   include "outlay.hpp"
 #   include "path_utility.hpp"
diff --git a/policy_view.hpp b/policy_view.hpp
index e53b36b..d52b6ec 100644
--- a/policy_view.hpp
+++ b/policy_view.hpp
@@ -26,7 +26,6 @@
 
 #include "product_editor.hpp"
 
-#include "obstruct_slicing.hpp"
 #include "uncopyable_lmi.hpp"
 
 #include <map>
@@ -35,10 +34,9 @@
 class PolicyDocument;
 class WXDLLIMPEXP_FWD_CORE wxTextCtrl;
 
-class PolicyView
-    :        public  ProductEditorView
-    ,        private lmi::uncopyable <PolicyView>
-    ,virtual private obstruct_slicing<PolicyView>
+class PolicyView final
+    :public  ProductEditorView
+    ,private lmi::uncopyable <PolicyView>
 {
   public:
     PolicyView();
diff --git a/preferences_model.hpp b/preferences_model.hpp
index fc88a2a..c06691c 100644
--- a/preferences_model.hpp
+++ b/preferences_model.hpp
@@ -31,16 +31,14 @@
 #include "datum_string.hpp"
 #include "mc_enum.hpp"
 #include "mc_enum_types.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "tn_range.hpp"
 #include "tn_range_types.hpp"
 
 #include <string>
 
-class LMI_SO PreferencesModel
-    :virtual private obstruct_slicing<PreferencesModel>
-    ,public MvcModel
+class LMI_SO PreferencesModel final
+    :public MvcModel
     ,public MemberSymbolTable<PreferencesModel>
 {
   public:
diff --git a/premium_tax.hpp b/premium_tax.hpp
index ae5b523..636f381 100644
--- a/premium_tax.hpp
+++ b/premium_tax.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "mc_enum_type_enums.hpp"       // mcenum_state
-#include "obstruct_slicing.hpp"
 #include "uncopyable_lmi.hpp"
 
 #include <vector>
@@ -85,9 +84,8 @@ class stratified_charges;
 ///
 /// start_new_year() should be improved as noted in its documentation.
 
-class premium_tax
-  :        private lmi::uncopyable <premium_tax>
-  ,virtual private obstruct_slicing<premium_tax>
+class premium_tax final
+    :private lmi::uncopyable <premium_tax>
 {
   public:
     premium_tax
diff --git a/product_data.hpp b/product_data.hpp
index 0c3138a..e0bd6d1 100644
--- a/product_data.hpp
+++ b/product_data.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "any_member.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 #include "xml_serializable.hpp"
@@ -40,8 +39,7 @@
 ///
 /// Implicitly-declared special member functions do the right thing.
 
-class glossed_string
-    :virtual private obstruct_slicing<glossed_string>
+class glossed_string final
 {
     friend class PolicyDocument;
 
@@ -79,11 +77,10 @@ template<> struct deserialized<product_data>
 ///
 /// Implicitly-declared special member functions do the right thing.
 
-class LMI_SO product_data
-    :        private lmi::uncopyable   <product_data>
-    ,virtual private obstruct_slicing  <product_data>
-    ,        public  xml_serializable  <product_data>
-    ,        public  MemberSymbolTable <product_data>
+class LMI_SO product_data final
+    :private lmi::uncopyable   <product_data>
+    ,public  xml_serializable  <product_data>
+    ,public  MemberSymbolTable <product_data>
 {
     typedef deserialized<product_data>::value_type value_type;
 
diff --git a/rate_table.cpp b/rate_table.cpp
index 2672a55..df8dcc6 100644
--- a/rate_table.cpp
+++ b/rate_table.cpp
@@ -834,9 +834,8 @@ boost::optional<field_and_value> parse_field_and_value
 namespace soa_v3_format
 {
 
-class table_impl
-    :        private lmi::uncopyable <table_impl>
-    ,virtual private obstruct_slicing<table_impl>
+class table_impl final
+    :private lmi::uncopyable <table_impl>
 {
   public:
     // Load the table data from the stream containing the table data in either
@@ -2346,9 +2345,8 @@ bool table::operator==(table const& other) const
     return impl_->is_equal(*other.impl_);
 }
 
-class database_impl
-    :        private lmi::uncopyable <database_impl>
-    ,virtual private obstruct_slicing<database_impl>
+class database_impl final
+    :private lmi::uncopyable <database_impl>
 {
   public:
     static fs::path get_index_path(fs::path const& path)
diff --git a/rate_table.hpp b/rate_table.hpp
index 1b219e9..e755358 100644
--- a/rate_table.hpp
+++ b/rate_table.hpp
@@ -24,7 +24,6 @@
 
 #include "config.hpp"
 
-#include "obstruct_slicing.hpp"
 #include "uncopyable_lmi.hpp"
 
 #include <boost/filesystem/path.hpp>
@@ -115,9 +114,9 @@ class table
 /// It is represented by two disk files with the extensions .dat and .ndx, the
 /// first containing the tables data and the second being the index allowing to
 /// locate a table by its number.
-class database
-    :        private lmi::uncopyable <database>
-    ,virtual private obstruct_slicing<database>
+
+class database final
+    :private lmi::uncopyable <database>
 {
   public:
     // Check if a database at the given path exists.
diff --git a/rounding_rules.hpp b/rounding_rules.hpp
index 21b1e2b..957eaea 100644
--- a/rounding_rules.hpp
+++ b/rounding_rules.hpp
@@ -27,7 +27,6 @@
 #include "any_member.hpp"
 #include "mc_enum.hpp"
 #include "mc_enum_types.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 #include "xml_serializable.hpp"
@@ -38,8 +37,7 @@
 ///
 /// Implicitly-declared special member functions do the right thing.
 
-class LMI_SO rounding_parameters
-    :virtual private obstruct_slicing<rounding_parameters>
+class LMI_SO rounding_parameters final
 {
     friend class rounding_rules;
 
@@ -90,11 +88,10 @@ class LMI_SO rounding_parameters
 ///   max- means the opposite.
 /// The 7702 and 7702A interest rate must be rounded up, if at all.
 
-class LMI_SO rounding_rules
-    :        private lmi::uncopyable   <rounding_rules>
-    ,virtual private obstruct_slicing  <rounding_rules>
-    ,        public  xml_serializable  <rounding_rules>
-    ,        public  MemberSymbolTable <rounding_rules>
+class LMI_SO rounding_rules final
+    :private lmi::uncopyable   <rounding_rules>
+    ,public  xml_serializable  <rounding_rules>
+    ,public  MemberSymbolTable <rounding_rules>
 {
     friend class RoundingDocument;
 
diff --git a/rounding_view.hpp b/rounding_view.hpp
index 43cba62..9f388b1 100644
--- a/rounding_view.hpp
+++ b/rounding_view.hpp
@@ -26,7 +26,6 @@
 
 #include "product_editor.hpp"
 
-#include "obstruct_slicing.hpp"
 #include "uncopyable_lmi.hpp"
 
 #include <map>
@@ -34,10 +33,9 @@
 class RoundingButtons;
 class RoundingDocument;
 
-class RoundingView
-    :        public  ProductEditorView
-    ,        private lmi::uncopyable <RoundingView>
-    ,virtual private obstruct_slicing<RoundingView>
+class RoundingView final
+    :public  ProductEditorView
+    ,private lmi::uncopyable <RoundingView>
 {
   public:
     RoundingView();
diff --git a/rtti_lmi.hpp b/rtti_lmi.hpp
index f011f9b..471b4c7 100644
--- a/rtti_lmi.hpp
+++ b/rtti_lmi.hpp
@@ -24,8 +24,6 @@
 
 #include "config.hpp"
 
-#include "obstruct_slicing.hpp"
-
 #if defined __GNUC__
 #   include <cstdlib>                   // std::free()
 #   include <cxxabi.h>
@@ -120,8 +118,7 @@ namespace lmi
 ///   lmi::TypeInfo(typeid(X));
 /// and resisting the temptation to add syntactic sugar.
 
-class TypeInfo
-    :virtual private obstruct_slicing<TypeInfo>
+class TypeInfo final
 {
     friend class ::RttiLmiTest;
 
diff --git a/single_cell_document.hpp b/single_cell_document.hpp
index cfc918f..6333c68 100644
--- a/single_cell_document.hpp
+++ b/single_cell_document.hpp
@@ -25,7 +25,6 @@
 #include "config.hpp"
 
 #include "input.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "uncopyable_lmi.hpp"
 #include "xml_lmi_fwd.hpp"
@@ -33,9 +32,8 @@
 #include <iosfwd>
 #include <string>
 
-class LMI_SO single_cell_document
-    :        private lmi::uncopyable <single_cell_document>
-    ,virtual private obstruct_slicing<single_cell_document>
+class LMI_SO single_cell_document final
+    :private lmi::uncopyable <single_cell_document>
 {
     friend class IllustrationDocument;
     friend class IllustrationView;
diff --git a/stratified_charges.cpp b/stratified_charges.cpp
index b3211ab..c551833 100644
--- a/stratified_charges.cpp
+++ b/stratified_charges.cpp
@@ -176,8 +176,7 @@ stratified_charges::stratified_charges(std::string const& 
filename)
 }
 
 stratified_charges::stratified_charges(stratified_charges const& z)
-    :obstruct_slicing  <stratified_charges>()
-    ,xml_serializable  <stratified_charges>()
+    :xml_serializable  <stratified_charges>()
     ,MemberSymbolTable <stratified_charges>()
 {
     ascribe_members();
diff --git a/stratified_charges.hpp b/stratified_charges.hpp
index b7ddde0..c3835c2 100644
--- a/stratified_charges.hpp
+++ b/stratified_charges.hpp
@@ -26,7 +26,6 @@
 
 #include "any_member.hpp"
 #include "mc_enum_type_enums.hpp"
-#include "obstruct_slicing.hpp"
 #include "so_attributes.hpp"
 #include "xml_serializable.hpp"
 
@@ -64,8 +63,7 @@ enum e_stratified
 ///
 /// Implicitly-declared special member functions do the right thing.
 
-class LMI_SO stratified_entity
-    :virtual private obstruct_slicing<stratified_entity>
+class LMI_SO stratified_entity final
 {
     friend class stratified_charges;
     friend class TierView;
@@ -98,10 +96,9 @@ class LMI_SO stratified_entity
 
 /// Rates that depend upon the amount they're multiplied by.
 
-class LMI_SO stratified_charges
-    :virtual private obstruct_slicing  <stratified_charges>
-    ,        public  xml_serializable  <stratified_charges>
-    ,        public  MemberSymbolTable <stratified_charges>
+class LMI_SO stratified_charges final
+    :public  xml_serializable  <stratified_charges>
+    ,public  MemberSymbolTable <stratified_charges>
 {
     friend class TierDocument;
 
diff --git a/test_coding_rules.cpp b/test_coding_rules.cpp
index 333bba5..143cb64 100644
--- a/test_coding_rules.cpp
+++ b/test_coding_rules.cpp
@@ -25,7 +25,6 @@
 #include "istream_to_string.hpp"
 #include "main_common.hpp"
 #include "miscellany.hpp"               // lmi_array_size(), split_into_lines()
-#include "obstruct_slicing.hpp"
 #include "uncopyable_lmi.hpp"
 
 #include <boost/filesystem/convenience.hpp> // fs::extension()
@@ -82,9 +81,8 @@ enum enum_kingdom
     ,e_c_or_cxx   = e_c          | e_cxx
     };
 
-class file
-    :        private lmi::uncopyable <file>
-    ,virtual private obstruct_slicing<file>
+class file final
+    :private lmi::uncopyable <file>
 {
   public:
     explicit file(std::string const& file_path);
diff --git a/text_view.hpp b/text_view.hpp
index 39c5543..53205a0 100644
--- a/text_view.hpp
+++ b/text_view.hpp
@@ -34,7 +34,6 @@
 
 #include "view_ex.hpp"
 
-#include "obstruct_slicing.hpp"
 #include "uncopyable_lmi.hpp"
 
 #include <wx/defs.h>                    // wx shared-library 'attributes'
@@ -49,10 +48,9 @@ class WXDLLIMPEXP_FWD_CORE wxTextCtrl;
 /// It's left in the repository, though, because it might be a useful
 /// model for some other feature someday.
 
-class TextEditView
-    :        public  ViewEx
-    ,        private lmi::uncopyable <TextEditView>
-    ,virtual private obstruct_slicing<TextEditView>
+class TextEditView final
+    :public  ViewEx
+    ,private lmi::uncopyable <TextEditView>
 {
     friend class TextEditDocument;
 
diff --git a/tier_view.hpp b/tier_view.hpp
index b73f1e1..591dd53 100644
--- a/tier_view.hpp
+++ b/tier_view.hpp
@@ -26,7 +26,6 @@
 
 #include "product_editor.hpp"
 
-#include "obstruct_slicing.hpp"
 #include "uncopyable_lmi.hpp"
 
 #include <memory>                       // std::shared_ptr
@@ -35,10 +34,9 @@ class TierDocument;
 class TierTableAdapter;
 class WXDLLIMPEXP_FWD_CORE wxTreeEvent;
 
-class TierView
-    :        public  TreeGridViewBase
-    ,        private lmi::uncopyable <TierView>
-    ,virtual private obstruct_slicing<TierView>
+class TierView final
+    :public  TreeGridViewBase
+    ,private lmi::uncopyable <TierView>
 {
   public:
     TierView();
diff --git a/yare_input.hpp b/yare_input.hpp
index bdb64f6..7a6061b 100644
--- a/yare_input.hpp
+++ b/yare_input.hpp
@@ -26,7 +26,6 @@
 
 #include "calendar_date.hpp"
 #include "mc_enum_type_enums.hpp"
-#include "obstruct_slicing.hpp"
 
 #include <string>
 #include <vector>
@@ -51,8 +50,7 @@ class Input;
 /// in particular dispensing with the considerable overhead of UDTs
 /// (mc_enum and tn_range classes) designed for interactive input.
 
-class yare_input
-    :virtual private obstruct_slicing<yare_input>
+class yare_input final
 {
   public:
     explicit yare_input(Input const&);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]