Skip to content

ENH: Implement concept checks with static_assert - #7108

Open
dzenanz wants to merge 4 commits into
InsightSoftwareConsortium:mainfrom
dzenanz:concept-static-assert
Open

dzenanz wants to merge 4 commits into
InsightSoftwareConsortium:mainfrom
dzenanz:concept-static-assert

Conversation

@dzenanz

@dzenanz dzenanz commented Nov 3, 2026

Copy link
Copy Markdown
Member

Reimplement itk::Concept as std::bool_constant traits checked by static_assert, enable concept checks that the removed ITK_USE_CONCEPT_CHECKING had silently disabled, and use plain static_assert where no concept is needed.

Commits
  1. ENH: Implement itk::Concept checks as static_assert of type traits: itkConceptChecking.h goes from 981 to 277 lines. Concepts use standard type traits or the detection idiom, and itkConceptMacro is a static_assert whose message names the check and the concept.
  2. ENH: Enable concept checks guarded by removed ITK_USE_CONCEPT_CHECKING: about 50 checks in 18 ingested remote modules never compiled. This commit enables them and fixes MovingImageDimension in PhaseCorrelationImageRegistrationMethod, which was derived from the fixed image type.
  3. STYLE: Replace dimension and type concept checks with static_assert: 162 checks become concept-free expressions or standard traits, such as ImageDimension == OutputImageDimension and std::is_same_v. The remaining 757 uses keep itkConceptMacro.
  4. STYLE: Remove "Begin/End concept checking" comments
Behavior changes
  • HasNumericTraits rejects types that have only the primary NumericTraits template. It caught itkNumericTraitsTest asserting HasNumericTraits<std::vector<float>> without including itkNumericTraitsStdVector.h; that specialization lacks IsPositive and the related functions, so the assertion is removed.
  • Other checks look only at declarations (SFINAE), not at function bodies.
  • Removed: ITK_CONCEPT_NO_CHECKING and the itkConceptConstraintsMacro and Concept::Detail helpers for custom concepts. The only external user found is dmritool's utlITKConceptChecking.h.
Local testing (macOS arm64, Apple clang 21)
  • C++ build of the default modules plus the 18 ingested modules: no errors.
  • Python wrapping build with the nightly MacOS-Rel-Python dashboard configuration (ITK_LEGACY_REMOVE=ON, ITKReview, Montage, RLEImage, …) plus the ingested modules: 3 failures, all in IsotropicWavelets' itk::Matrix<std::complex<T>> and VariableSizeMatrix<std::complex<T>> wrappers. GetInverse reaches itkBridgeMathSVD.h and itkBridgeEigenDecompositionSignConvention.h, which compare complex values with < and >. This reproduces on unmodified upstream/main, and this PR touches neither file.
  • ctest: 6590 of 6623 pass, including all C++ tests. Of the 33 Python failures, 32 come from _IsotropicWaveletsPython not building (see above). The other is PythonMedianImageFilterTest, a Python 3.15 typing error in get_type_hints.
  • Every concept was checked with pass and fail cases under Apple clang and GCC 16, in C++17 and C++20.
AI assistance
  • Tool: Claude Code
  • Role: designed the trait-based header, wrote the conversion scripts for commits 2–4, and ran the local builds and tests above.
  • The author reviewed the commits.

🤖 Generated with Claude Code

Each concept is now a std::bool_constant computed with standard type
traits or the detection idiom, and itkConceptMacro expands to a
static_assert naming the failed check. This replaces the Boost-derived
Constraints/Enforcer machinery, its compiler-specific variants, and the
ITK_CONCEPT_NO_CHECKING switch.

HasNumericTraits now also rejects types that only have the primary
NumericTraits template.
ITK_USE_CONCEPT_CHECKING is no longer defined, so checks in modules
ingested from remote repositories never compiled. Enable them, fix
the MovingImageDimension definition they exposed in
PhaseCorrelationImageRegistrationMethod, and add checks to
RieszFrequencyFilterBankGenerator and MedialThicknessImageFilter3D.
Remove a check on a fixed type and empty placeholder blocks.
@github-actions github-actions Bot added type:Enhancement Improvement of existing methods or implementation type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct area:Bridge Issues affecting the Bridge module area:Core Issues affecting the Core module area:Filtering Issues affecting the Filtering module area:Registration Issues affecting the Registration module area:Segmentation Issues affecting the Segmentation module area:Video Issues affecting the Video module labels Nov 3, 2026

@hjmjohnson hjmjohnson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AWESOME!!!

Only checks expressible without itk::Concept are converted: dimension
comparisons, SameType, integer and signedness, and constructibility.
@dzenanz
dzenanz force-pushed the concept-static-assert branch from 1919d32 to b20af2c Compare November 4, 2026 19:06
@dzenanz

dzenanz commented Nov 4, 2026

Copy link
Copy Markdown
Member Author

Thank you for improving this change Niels!

@dzenanz
dzenanz marked this pull request as ready for review November 4, 2026 19:07
@greptile-apps

greptile-apps Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 4/5 Tier: apex

[Medium impact] The PR changes compile-time type checks across many ITK modules.

Fix the complex-image build failure and remove the unused include to meet the project standard before merging.

Findings

  1. P1 Complex images stop compiling ▶
  2. P2 Pixel trait queries fail ▶
  3. P2 False results lack tests ▶
  4. P2 Unused include violates project standards ▶

Summary

Replaces itk::Concept checks with boolean traits and static_assert, enables dormant checks, and corrects the moving-image dimension in Montage.

  • ITK templates check their type requirements at compile time.

Reviews (1) · Last reviewed commit: "STYLE: Remove "Begin/End concept checkin..." · Reviewed by Greptile

// Begin concept checking
itkConceptMacro(Input1ConvertableToOutputCheck, (Concept::Convertible<Input1PixelType, OutputPixelType>));
itkConceptMacro(Input2ConvertableToOutputCheck, (Concept::Convertible<Input2PixelType, OutputPixelType>));
itkConceptMacro(Input1GreaterThanInput2Check, (Concept::GreaterThanComparable<Input1PixelType, Input2PixelType>));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Complex images stop compiling

MaximumAbsoluteValueImageFilter<Image<std::complex<float>, 3>> now fails to compile because this enabled check requires > and >= on complex pixels. The filter compares their magnitudes through Math::Absolute, which returns a floating-point value, then returns the selected complex pixel. Check the magnitude types instead, or remove the raw-pixel ordering check.

Suggested change
itkConceptMacro(Input1GreaterThanInput2Check, (Concept::GreaterThanComparable<Input1PixelType, Input2PixelType>));

};

/** Concept requiring T to have a trait called ValueType */
struct HasPixelTraits : std::bool_constant<Detail::IsValidExpression<Detail::PixelTraitsMembers, T>>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Pixel trait queries fail

HasPixelTraits<std::complex<double>>::value produces a compile error instead of false. Looking up PixelTraits<T>::ValueType creates the primary PixelTraits class, whose own TPixelType::ValueType declaration fails outside the scope that IsValidExpression can catch. Callers therefore cannot use this boolean trait in if constexpr to choose a fallback. Make the primary PixelTraits safe to probe and add a false-case test.

Comment on lines +59 to +67
template <typename TVoid, template <typename...> typename TExpression, typename... TArgs>
struct IsValidExpressionImpl : std::false_type
{};
template <bool>
struct UniqueType_bool
template <template <typename...> typename TExpression, typename... TArgs>
struct IsValidExpressionImpl<std::void_t<TExpression<TArgs...>>, TExpression, TArgs...> : std::true_type
{};
/** True when the type alias TExpression<TArgs...> is well-formed (detection idiom). */
template <template <typename...> typename TExpression, typename... TArgs>
inline constexpr bool IsValidExpression = IsValidExpressionImpl<void, TExpression, TArgs...>::value;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 False results lack tests

The rewritten traits have no committed tests for false results. The remaining checks in itkNumericTraitsTest.cxx all require success, and the invalid std::vector<float> check is deleted rather than changed to assert false. Commit the local pass/fail cases as positive and negative static_assert tests, including rejected HasNumericTraits and Convertible cases. Otherwise CI cannot catch a check that silently starts accepting invalid types.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

#include "itkNumericTraits.h"
#include <iostream>
#include <type_traits>
#include <utility>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unused include violates project standards

The added <utility> include has no user. Lvalue replaces std::declval, and nothing else here uses that header. The project standard says “Include only what you use.” Remove the include before merging to satisfy that requirement.

Suggested change
#include <utility>

Context Used: AGENTS.md (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:Bridge Issues affecting the Bridge module area:Core Issues affecting the Core module area:Filtering Issues affecting the Filtering module area:Registration Issues affecting the Registration module area:Segmentation Issues affecting the Segmentation module area:Video Issues affecting the Video module type:Enhancement Improvement of existing methods or implementation type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants