This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

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>>;
    […]