Apply Rule of Zero across remaining utility/ empty destructors (#694)
## Summary
Bundle of small Rule-of-Zero / clarity fixes across `utility/` for
classes
not covered by any other open PR. All changes are observably no-ops at
runtime (each destructor body either was empty or `= default`); the goal
is to remove redundant declarations and document a deliberate
non-trivial
case.
- **Remove empty `~Foo() {}`** where the implicit destructor is already
correct (virtual is preserved via the base class when relevant):
`Bound`, `Exception`, `ocstream`, `AutoKey`, `UserKey`.
- **Convert `~Foo() {}` to `~Foo() = default;`** for polymorphic root
classes (no virtual base destructor to inherit), so the destructor
stays virtual: `Show`, `WidgetFactory`, `irstream`, `orstream`, `Key`,
`Option`.
- **Drop matching `= default` destructor pairs (.hh decl + .cc def)**
for
classes that inherit from `utility::VirtualBase`, which already
supplies a `virtual ~VirtualBase() = default;`: `heap`,
`subset_mapping`, `recent_history_queue`, `GeneralFileContents`,
`GeneralFileContentsVector`, `Tag`.
- **`utility/io/mpistream.hh`**: the destructor of `basic_mpi_streambuf`
is **not** trivial — it calls `flush_final()`, which sends the close
message on the MPI channel. Add explicit `= delete` for its copy
constructor and copy-assignment so an accidental copy can't trigger
the side effect twice. Also replace the empty
`~basic_mpi_ostream() override {}` with `= default`.