InsightSoftwareConsortium / InsightSoftwareConsortium/ITK

ENH: Deprecate the `itk::mpl` boolean metafunctions and the `itk::TrueType`/`itk::FalseType` aliases in favor of `<type_traits>`

Open
#6,724 3 comments 1 reaction 0 assignees View on GitHub
type:Enhancement
Dominant language
C++
Stars
1.7k
Forks
748
Avg merge
1d 1h
Merged PRs (30d)
64

Description

`itkMetaProgrammingLibrary.h`'s boolean metafunctions (`mpl::And/Or/Not/Xor/AndC/OrC/NotC/XorC`) and the `itk::TrueType`/`itk::FalseType` aliases predate C++17 and map onto `std::conjunction`/`std::disjunction`/`std::negation`/`std::bool_constant`. The header itself already predicts the alias removal (line 244: *"Expect itk::TrueType and itk::False type to be deprecated."*).

This is a single migration with a forced ordering — the aliases cannot be deprecated before the combinators — so it is filed as one issue with two stages. It follows the per-trait precedent set by #6573 (`mpl::IsNumber`).

Why one issue and not two (the Value vs value hazard)

`mpl::TrueType`/`FalseType` expose a **capital-V** static member:

```cpp
// Modules/Core/Common/include/itkMetaProgrammingLibrary.h:41-63
struct TrueType { using ValueType = bool; using Type = TrueType; static constexpr ValueType Value = true; operator ValueType() { return Value; } };
struct FalseType { using ValueType = bool; using Type = FalseType; static constexpr ValueType Value = false; operator ValueType() { return Value; } };
```

and the combinators read that member:

```cpp
// :111-143
template
struct Or : OrC {};
template
struct And : AndC {};
```

`std::true_type` exposes lowercase `value`. So rebasing `IsArray` onto `std::bool_constant` while `mpl::And`/`Or` still read `::Value` is a hard compile break. The two stages must land in order (or in one PR).

Current in-tree inventory (re-derived on main, 2026-07-29)

```
git grep -oh -E "mpl::[A-Za-z]+" -- ':!Modules/ThirdParty' ':!Documentation' | sort | uniq -c
```

| entity | count | disposition |
|---|---|---|
| `mpl::IsArray` | 24 | ITK-specific, **must survive** — rebase onto `std::bool_constant` |
| `mpl::AndC` | 5 | → `std::conjunction` / plain `&&` on `_v` |
| `mpl::And` | 4 | → `std::conjunction` |
| `mpl::Or` | 2 | → `std::disjunction` |
| `mpl::Not` | 2 | → `std::negation` |
| `mpl::PromoteType` | 5 | **out of scope** — semantics differ from `std::common_type`; needs its own analysis |
| `mpl::IsSmartPointer` | 2 | ITK-specific, **must survive** |
| `mpl::TrueType`/`FalseType` (qualified) | 2 | → `std::true_type`/`std::false_type` |

Header map (`itkMetaProgrammingLibrary.h`, 250 lines total):
`TrueType`:41, `FalseType`:54, `OrC`:92, `Or`:111, `AndC`:124, `And`:143, `XorC`:155, `NotC`:188, `Not`:209, `IsSmartPointer`:217, alias block:243-246.

The alias block, verbatim:

```cpp
// Modules/Core/Common/include/itkMetaProgrammingLibrary.h:243-246
// TrueType and FalseType have moved to itk::mpl.
// Expect itk::TrueType and itk::False type to be deprecated.
using mpl::TrueType;
using mpl::FalseType;
```

Consumers that must move in lockstep

- `Modules/Core/Common/include/itkVariableLengthVector.h:1171-1180` — `IsArray` derives from **unqualified** `FalseType`/`TrueType` (resolving through the `itk::` aliases):
```cpp
template struct IsArray : FalseType {};
template struct IsArray> : TrueType {};
template
struct IsArray> : TrueType {};
```
- `itkVariableLengthVector.h:1227/1245/1261` — `std::enable_if_t, mpl::Not>>::Value, unsigned int>` SFINAE guards.
- `itkVariableLengthVector.h:1305-1339` — `CanBeAddedOrSubtracted`, `CanBeMultiplied`, `CanBeDivided` in `itk::VariableLengthVectorExpression::op`, already partly modernized by #6573 to `mpl::AndC<..., std::is_arithmetic_v<...>>` but still combinator-based.
- `Modules/Core/Common/test/itkMetaProgrammingLibraryTest.cxx:45-89` — exhaustive `static_assert`s over `Or`/`And`/`Xor`/`Not` with `TrueType`/`FalseType`; must be rewritten in the same PR.
- `Modules/Core/Common/include/itkIsNumber.h:40-81` — already legacy-gated by #6573 but still derives from `mpl::TrueType`/`FalseType`, so it stays inside the `!ITK_LEGACY_REMOVE` branch.

**Not a consumer, despite the common assumption:** `itkBinaryOperationConcept.h` uses only `mpl::PromoteType` (lines 50, 64, 78, 92) — no boolean combinators. It is unaffected.

**Precedent that `std::` types are drop-in:** `Modules/Core/Common/include/itkImageAlgorithm.h:45-46` already defines its own class-scope `using TrueType = std::true_type; using FalseType = std::false_type;` and uses them as dispatch tags at :148/:157 and in the `.hxx` at :73/:95.

Stage 1 — combinators (must land first)

1. Migrate `itkVariableLengthVector.h` call sites (`:1227`, `:1245`, `:1261`, `:1305-1339`) to `std::conjunction_v` / `std::disjunction_v` / `std::negation`, or to plain `&&`/`||` on `_v` values where the struct form is not needed for SFINAE.
2. Rewrite `itkMetaProgrammingLibraryTest.cxx:45-89` against the `std::` forms.
3. Legacy-gate the boolean section of `itkMetaProgrammingLibrary.h` (lines 41-215, i.e. `TrueType` through `Not`, including `Xor`/`XorC`) behind `#if !defined(ITK_LEGACY_REMOVE)` with an `#else` `#error` branch — the exact shape #6573 gave `itkIsNumber.h` (`:24` / `:88`).

Stage 2 — the itk:: aliases

4. Rebase `IsArray` (`itkVariableLengthVector.h:1171-1180`) and `IsSmartPointer` (`itkMetaProgrammingLibrary.h:217-227`) onto `std::bool_constant` / `std::false_type` / `std::true_type`.
5. Legacy-gate `using mpl::TrueType; using mpl::FalseType;` (`:243-246`) and delete the prophetic comment.
6. Add a migration-guide entry in `Documentation/docs/migration_guides/itk_6_migration_guide.md`: `itk::TrueType`→`std::true_type`, `itk::FalseType`→`std::false_type`, `mpl::And/Or/Not`→`std::conjunction/disjunction/negation`.

Scope boundaries and hazards

- **`mpl::PromoteType` is explicitly out of scope.** Its promotion rules are *not* identical to `std::common_type`; it needs a separate analysis and its own issue.
- **`IsArray` and `IsSmartPointer` must survive** — they have no `std::` equivalent. `itkMetaProgrammingLibrary.h` therefore stays a live header; it should *not* be added to the compatibility-only exclusion list in `Utilities/Maintenance/BuildHeaderTest.py` (unlike `itkEnableIf.h` / `itkIsSame.h` / `itkIsBaseOf.h` / `itkIsConvertible.h` / `itkIsNumber.h`).
- **Semantic-widening caution, from the #6573 review:** a `std::` trait can be wider than the mpl one it replaces (`std::is_arithmetic_v` is `true` where `mpl::IsNumber` was `false`). Check every combinator call site for the analogous widening before swapping.
- `mpl::Xor`/`XorC` (`:155`) have no in-tree users outside the unit test but must be gated with the rest.

Related

- #6573 — "Deprecate mpl::IsNumber" (merged 2026-07-10) — the template for the legacy-gating pattern.
- #2730 — earlier mpl deprecations referenced by #6573.
- `Modules/Core/Common/include/itkMetaProgrammingLibrary.h` — the target header.

Contributor guide

Open the contributing guide

Research direction

Start with Modules/Core/Common/include/itkMetaProgrammingLibrary.h and run the issue’s git grep inventory, then inspect the listed consumers in itkVariableLengthVector.h and itkIsNumber.h. Run Modules/Core/Common/test/itkMetaProgrammingLibraryTest.cxx while handling the combinator stage before the alias stage. Done means the listed boolean APIs are gated or replaced in order, surviving traits remain usable, tests pass, and the ITK 6 migration guide records the replacements.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
developer-experience, documentation
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.