Skip to content

Apply Rule of Zero across utility/ helpers - #692

Merged
lyskov merged 2 commits into
RosettaCommons:mainfrom
lyskov-ai:refactor/utility-iterator-rule-of-zero
May 28, 2026
Merged

Apply Rule of Zero across utility/ helpers#692
lyskov merged 2 commits into
RosettaCommons:mainfrom
lyskov-ai:refactor/utility-iterator-rule-of-zero

Conversation

@lyskov-ai

Copy link
Copy Markdown
Contributor

Summary

Remove user-declared destructors and trivial copy ctor/assignment implementations whose bodies are equivalent to the compiler-generated defaults. The implicit special members are correct in every case (no owning raw pointers, no side effects in the removed bodies, virtual destructor inheritance preserved through base classes).

utility/graph/ — non-owning iterator/element helpers

  • Graph.hh: EdgeListElement, EdgeListIterator, EdgeListConstIterator — drop user dtor and the = default copy ctor / assignment.
  • Digraph.hh: DirectedEdgeListElement, DirectedEdgeListIterator, DirectedEdgeListConstIterator — drop user dtor and member-wise copy ctor / assignment.
  • ArrayPool.hh (Array0): drop user dtor, copy ctor, and self-assignment-guarded copy assignment.
  • LowMemGraph.hh (LowMemGraphBase): drop empty override dtor (utility::VirtualBase supplies the virtual destructor).
  • UpperEdgeGraph.hh: drop the empty UEEdge dtor and ~UpperEdgeGraph() override = default;.

LowMemNode / LowMemEdge are intentionally left untouched — their explicit destructor declarations anchor a load-bearing comment about deliberately not making the destructor virtual.

utility/

  • DereferenceIterator.hh (DereferenceIterator): drop empty user dtor.

utility/options/ — empty overriding destructors

Drop ~XxxOption() override {} from the eight leaf scalar/vector option classes. The implicit destructor is virtual via inheritance from Option (which declares a virtual destructor), so dynamic dispatch is preserved.

  • BooleanOption.hh, BooleanVectorOption.hh
  • FileOption.hh, FileVectorOption.hh
  • IntegerOption.hh, IntegerVectorOption.hh
  • RealOption.hh, RealVectorOption.hh

The remaining option classes with the same pattern (PathOption, StringOption, ResidueChainVectorOption, ScalarOption, ScalarOption_T_, VectorOption, VectorOption_T_) can be addressed in a follow-up; the eight here form a coherent leaf-scalar-plus-vector subset.

Test plan

  • cd source && python3 ./scons.py -j16 mode=debug — clean (no errors)
  • 90 standard tests CI run

Remove user-declared destructors and trivial copy ctor/assignment
implementations whose bodies are equivalent to the compiler-generated
defaults. The implicit special members are correct in every case:

* utility/DereferenceIterator.hh: empty user dtor.
* utility/graph/ArrayPool.hh (Array0): empty dtor plus member-wise
  copy ctor and self-assignment-guarded copy assignment.
* utility/graph/Graph.hh / Digraph.hh: empty dtor and = default /
  member-wise copy ops on EdgeListElement, EdgeListIterator,
  EdgeListConstIterator and the Directed* counterparts (non-owning
  raw pointers, default copy is correct).
* utility/graph/LowMemGraph.hh (LowMemGraphBase): empty override dtor;
  base utility::VirtualBase already supplies a virtual destructor.
* utility/graph/UpperEdgeGraph.hh: empty UEEdge dtor and the
  ~UpperEdgeGraph() override = default declaration.
* utility/options/{Boolean,File,Integer,Real}Option(.hh) and their
  *VectorOption.hh counterparts: empty ~XxxOption() override {}; the
  base option classes' virtual destructors are still inherited.
UpperEdgeGraph::get_vertex_ptr and ::note_edge_deleted are called from
the friend class UEEdge (constructors at lines 314/315/325/326 and
delete_edge at line 342), but cppcheck does not trace template friend
usage and flags them as unusedPrivateFunction.
@lyskov
lyskov merged commit 1886935 into RosettaCommons:main May 28, 2026
1 check passed
lyskov pushed a commit that referenced this pull request Jun 7, 2026
## Summary

Drop user-declared empty destructors from the `utility/options/` and
`utility/options/keys/` class hierarchies. The implicit destructor
preserves virtual dispatch in every case via inherited virtual
destructors:

- All option classes inherit (transitively) from
`utility::options::Option`, which declares `virtual ~Option()`.
- All option-key classes inherit (transitively) from
`utility::keys::Key`, which declares `virtual ~Key()`.

No class touched here owns a raw resource, declares a non-trivial
destructor body, or has a user-declared copy/move that would suppress
the implicit destructor.

### `utility/options/` — abstract bases and remaining leaf option
classes

* Abstract / templated bases: `ScalarOption`, `ScalarOption_T_`,
`VectorOption`, `VectorOption_T_`, `AnyOption`, `AnyVectorOption`.
* Leaf options: `PathOption`, `PathVectorOption`, `StringOption`,
`StringVectorOption`, `ResidueChainVectorOption`.

`AnyOption` / `AnyVectorOption` used the `virtual` keyword on the empty
body; the rest used `override {}`. Both forms are equivalent to the
implicit virtual destructor here.

### `utility/options/keys/` — base + 16 leaf key types

* Base: `OptionKey`.
* Leaves: `AnyOptionKey`, `AnyVectorOptionKey`, `BooleanOptionKey`,
`BooleanVectorOptionKey`, `FileOptionKey`, `FileVectorOptionKey`,
`IntegerOptionKey`, `IntegerVectorOptionKey`, `PathOptionKey`,
`PathVectorOptionKey`, `RealOptionKey`, `RealVectorOptionKey`,
`ResidueChainVectorOptionKey`, `ScalarOptionKey`, `StringOptionKey`,
`StringVectorOptionKey`, `VectorOptionKey`.

This is the natural follow-up to #692, which intentionally deferred this
batch. With this PR, the entire `utility/options*`
empty-virtual-destructor pattern is cleaned up.

29 files, 156 deletions, 0 additions. Debug build clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants