Skip to content

SFINAE to Concepts migration #7530

@DennisOSRM

Description

@DennisOSRM

Migration plan to replace SFINAE/detection idioms with C++20 concepts. Draft PR: #7529

SFINAE → Concepts migration plan

Overview

Replace ad-hoc SFINAE and detection-idiom patterns with C++20 concepts across the repository. This will make compile-time constraints explicit, simplify overload resolution, improve diagnostics and maintainability, and enable safer incremental refactors.

Goals

  • Replace uses of std::enable_if, std::void_t, custom detection traits and similar SFINAE patterns with clear C++20 concepts and requires-clauses.
  • Keep runtime behavior unchanged and preserve runtime polymorphism where required.
  • Migrate incrementally with small, reviewable PRs and CI enforcement for C++20.

Scope (initial inventory)

Initial scan shows SFINAE / detection idiom uses in:

  • include/util/graph_traits.hpp
  • include/util/alias.hpp
  • include/util/packed_vector.hpp
  • include/util/indexed_data.hpp
  • include/util/filtered_integer_range.hpp
  • include/util/static_rtree.hpp
  • include/util/packed_vector.hpp
  • include/partitioner/* (cell_storage.hpp, multi_level_partition.hpp)
  • include/extractor/node_data_container.hpp
  • include/server/api/parameters_parser.hpp
  • include/guidance/turn_data_container.hpp
  • others discovered by repo-wide grep for enable_if / void_t / is_detected

Approach & Phases

  1. Inventory & analysis

    • Run an automated scan (ripgrep/clang-query) to enumerate all SFINAE patterns and categorize them by pattern, file, and risk (low/medium/high).
    • Produce a spreadsheet or JSON mapping: file -> pattern -> instances -> suggested concept.
  2. Design PoC / Policy

    • Formalize guidelines for when to prefer standard concepts (std::integral, std::derived_from, etc.) vs custom concepts.
    • Define a set of reusable concepts in include/concepts/ (or similar) and examples.
    • Complete two PoCs: RoutingAlgorithm concept (done) and GraphTraits -> concept.
  3. CI and Tooling

    • Add CI job(s) compiling with -std=c++20 on multiple compilers (Clang/GCC) and platforms.
    • Add tests that assert critical concept constraints (static_asserts) and compile-examples.
  4. Incremental migration

    • Create small PRs for low-risk modules first (util/*), then mid-risk (guidance/turn_data_container, server/api), then high-risk (partitioner, extractor).
    • Each PR must build on CI, include unit/regression checks and clear commit messages with rationale.
  5. Cleanup & Documentation

    • Remove deprecated SFINAE helpers only after consumers migrated.
    • Update CONTRIBUTING.md with concept guidelines and examples.

Tasks and Milestones

  • Inventory (sfinae-inventory)
  • PoC: graph_traits -> concept (sfinae-poc-graph-traits)
  • PoC: packed_vector -> concepts (sfinae-poc-packed-vector)
  • Migrate util/* (sfinae-migrate-util)
  • Migrate partitioner/extractor (sfinae-migrate-partitioner)
  • Add CI concept checks (sfinae-ci)
  • Documentation and examples (sfinae-docs)

Project Tracking

  • Create a GitHub project board (repository-scoped) named: "SFINAE → Concepts migration" with columns: Backlog, In Progress, Review, Done.
  • Track each task above as a card; link PRs and issues.

Automation & Helpers

  • Provide a small scanning script (scripts/find_sfinae.sh) that uses ripgrep to find patterns and outputs JSON.
  • Provide replacement snippets and templates for common transformations (enable_if -> requires, detection trait -> requires expression).
  • Consider writing clang-tidy checks or clang-based refactor tooling for bulk changes if many mechanical replacements are required.

Risks & Mitigations

  • Risk: single change causes many cascade compile errors. Mitigation: do per-module PRs and keep SFINAE helpers working as fallbacks until consumers are migrated.
  • Risk: compiler differences in concept diagnostics. Mitigation: enforce CI across compilers and keep patch size small.
  • Risk: behavioral regressions from incorrect replacements. Mitigation: rely on unit tests and acceptance tests before merge.

Acceptance criteria

  • Each migrated module compiles under C++20 and passes existing tests.
  • CI includes C++20 concept checks and is green for all PRs.
  • A documented set of reusable concepts is available in-tree.

Next steps

  • Finalize inventory and confirm the candidate list (sfinae-inventory).
  • Start PoC on include/util/graph_traits.hpp (sfinae-poc-graph-traits).
  • Create GitHub project board and add initial tasks/cards.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions