3895. Various relation concepts are missing default values of the second template parameters

Section: 18.3 [concepts.syn], 24.2 [iterator.synopsis] Status: New Submitter: blacktea hamburger Opened: 2023-02-25 Last modified: 2023-03-22

Priority: 3

View all issues with New status.

Discussion:

std::indirect_equivalence_relation and std::indirect_strict_weak_order have default values for the second template parameters:

template<class F, class I1, class I2 = I1>
  concept indirect_equivalence_relation = see below;

template<class F, class I1, class I2 = I1>
  concept indirect_strict_weak_order = see below;

But std::relation, std::equivalence_relation, std::strict_weak_order, and std::indirect_binary_predicate are missing such default values:

template<class R, class T, class U>
  concept relation = see below;

template<class R, class T, class U>
  concept equivalence_relation = see below;

template<class R, class T, class U>
  concept strict_weak_order = see below;
  
template<class F, class I1, class I2>
  concept indirect_binary_predicate = see below;

That makes them inconsistent and it should not be expected.

[2023-03-22; Reflector poll]

Set priority to 3 after reflector poll. "Borderline design change." "Should not change indirect_binary_predicate." "NAD, write a paper." "NAD, default argument would make typos compile. Explicit is good."

Proposed resolution:

This wording is relative to N4928.

  1. Modify 18.3 [concepts.syn], header <concepts> synopsis, as indicated:

    // all freestanding
    namespace std {
      […]
      
      // 18.7.5 [concept.relation], concept relation
      template<class R, class T, class U = T>
        concept relation = see below;
      
      // 18.7.6 [concept.equiv], concept equivalence_relation
      template<class R, class T, class U = T>
        concept equivalence_relation = see below;
      
      // 18.7.7 [concept.strictweakorder], concept strict_weak_order
      template<class R, class T, class U = T>
        concept strict_weak_order = see below;
    }
    
  2. Modify 18.7.5 [concept.relation] as indicated:

    template<class R, class T, class U = T>
      concept relation =
        predicate<R, T, T> && predicate<R, U, U> &&
        predicate<R, T, U> && predicate<R, U, T>;
    
  3. Modify 18.7.6 [concept.equiv] as indicated:

    template<class R, class T, class U = T>
      concept equivalence_relation = relation<R, T, U>;
    
  4. Modify 18.7.7 [concept.strictweakorder] as indicated:

    template<class R, class T, class U = T>
      concept strict_weak_order = relation<R, T, U>;
    
  5. Modify 24.2 [iterator.synopsis], header <iterator> synopsis, as indicated:

    […]
    namespace std {
      […]
      // 24.3.6.3 [indirectcallable.indirectinvocable], indirect callables
      […]
      template<class F, class I1, class I2 = I1>
        concept indirect_binary_predicate = see below; // freestanding
    
      template<class F, class I1, class I2 = I1>
        concept indirect_equivalence_relation = see below; // freestanding
      […]
    }
    
  6. Modify 24.3.6.3 [indirectcallable.indirectinvocable] as indicated:

    -1- The indirect callable concepts are used to constrain those algorithms that accept callable objects (22.10.4 [func.require]) as arguments.

    […]
    template<class F, class I1, class I2 = I1>
      concept indirect_binary_predicate =
        indirectly_readable<I1> && indirectly_readable<I2> &&
        copy_constructible<F> &&
        predicate<F&, iter_value_t<I1>&, iter_value_t<I2>&> &&
        predicate<F&, iter_value_t<I1>&, iter_reference_t<I2>> &&
        predicate<F&, iter_reference_t<I1>, iter_value_t<I2>&> &&
        predicate<F&, iter_reference_t<I1>, iter_reference_t<I2>> &&
        predicate<F&, iter_common_reference_t<I1>, iter_common_reference_t<I2>>;
    […]