contracts#

The contracts module provides C++ contracts support for HPX with intelligent fallback to assertions when native contracts are not available. This module implements a forward-compatible API that works across different C++ standards and compiler capabilities.

The module provides three primary macros: HPX_PRE, HPX_POST, and HPX_CONTRACT_ASSERT. These macros automatically adapt their behavior based on compiler capabilities:

  • When C++26 native contracts are available (__cpp_contracts defined), they map to standard contract syntax

  • When HPX_WITH_CX26_CONTRACTS=OFF, preconditions and postconditions become no-ops while contract assertions remain available as enhanced assertions

Configuration#

Enable contracts in CMake:

cmake -DHPX_WITH_CXX26_CONTRACTS=ON -DCMAKE_CXX_STANDARD=26

Enable contract-enhanced assertions (optional):

cmake -DHPX_WITH_CXX26_CONTRACTS=ON -DHPX_CONTRACTS_WITH_ASSERTS_AS_CONTRACT_ASSERTS=ON

Contract assertions work even when contracts are disabled:

cmake -DHPX_WITH_CXX26_CONTRACTS=OFF  # HPX_CONTRACT_ASSERT still maps to HPX_ASSERT

Advanced Features#

Contract-Enhanced Assertions#

When HPX_CONTRACTS_WITH_ASSERTS_AS_CONTRACT_ASSERTS=ON is enabled, regular HPX_ASSERT calls are automatically upgraded to use contract assertions in C++26 mode:

void example_function(int value)
{
    HPX_ASSERT(value > 0);  // Becomes contract_assert(value > 0) in C++26 mode
    // ... rest of function
}

Warning

Enhanced assertions only provide benefits when native C++26 contracts are supported by the compiler. Without native contract support, HPX_ASSERT -> HPX_CONTRACT_ASSERT -> HPX_ASSERT (no enhancement). CMake will issue a warning if you enable this option without native contract support.

This provides enhanced contract semantics throughout your existing codebase without requiring changes to assertion code. The transformation occurs in the contracts module (contracts.hpp) where the HPX_ASSERT macro is overridden to use HPX_CONTRACT_ASSERT when HPX_WITH_ASSERTS_AS_CONTRACT_ASSERTS=ON:

  • HPX_WITH_CXX26_CONTRACTS=ON - Contracts module is enabled

  • HPX_CONTRACTS_WITH_ASSERTS_AS_CONTRACT_ASSERTS=ON - Assertion enhancement is enabled

The implementation works by redefining HPX_ASSERT in contracts.hpp to use HPX_CONTRACT_ASSERT, which automatically adapts to the current contract mode (native C++26 contracts or assertion fallback). This ensures all existing HPX_ASSERT calls throughout the HPX codebase automatically gain contract semantics when available.

Usage Examples#

Preconditions and postconditions using declaration syntax (C++26):

int divide(int a, int b) HPX_PRE(b != 0)
{
    return a / b;
}

int factorial(int n) HPX_PRE(n >= 0) HPX_POST(r; r > 0)
{
    return n <= 1 ? 1 : n * factorial(n - 1);
}

Contract assertions (available in all modes):

void process_array(std::vector<int>& arr, size_t index)
{
    HPX_CONTRACT_ASSERT(index < arr.size());
    arr[index] *= 2;
}

Design Philosophy#

HPX_CONTRACT_ASSERT: Enhanced assertion mechanism

Available even when HPX_WITH_CONTRACTS=OFF because it provides value as an enhanced assertion. Maps to HPX_ASSERT in all configurations.

HPX_PRE/HPX_POST: True contract syntax

Represent language-level contract semantics. When contracts are enabled but native C++26 contracts are not available, these become no-ops to maintain forward compatibility. When HPX_WITH_CONTRACTS=OFF, they are also no-ops. This prepares for C++26 migration where they will be attached to function declarations rather than used in function bodies.

Migration Strategy#

The module is designed for smooth migration to C++26 native contracts:

Current (transition mode):

int func(int x)
{
    HPX_PRE(x > 0);    // No-op in fallback mode, active in native mode
    return x;
}

Target (C++26 native):

int func(int x) HPX_PRE(x > 0)
{
    return x;
}

Note: In fallback mode, HPX_PRE and HPX_POST become no-ops to maintain forward compatibility and avoid performance overhead. Use HPX_CONTRACT_ASSERT when you need runtime validation in all modes.

Testing#

The module includes comprehensive testing with automatic compiler capability detection. Tests are organized into three categories:

  • Declaration tests: Test C++26 native contract syntax when __cpp_contracts is available

  • Fallback tests: Test assertion fallback behavior when contracts are not natively supported

  • Disabled tests: Test no-op behavior when contracts are disabled

The test suite automatically detects compiler capabilities at configure time and builds only the appropriate tests for the current configuration.

See the API reference of the module for more details.