Title
Constraints for Source in §[fs.path.req] insufficiently constrainty
Status
c++20
Section
[fs.path.req]
Submitter
Casey Carter

Created on 2019-08-02.00:00:00 last changed 45 months ago

Messages

Date: 2019-08-17.17:34:27

Proposed resolution:

This wording is relative to N4830.

  1. Modify [fs.path.req] as indicated:

    -2- Functions taking template parameters named Source shall not participate in overload resolution unless Source denotes a type other than path, and either

    […]

Date: 2019-08-17.00:00:00

[ 2019-08-17 Issue Prioritization ]

Status to Tentatively Ready and priority to 0 after seven positive votes on the reflector.

Date: 2019-08-02.00:00:00

std::filesystem::path has a number of functions - notably including a conversion constructor template ([fs.path.construct]) and assignment operator template ([fs.path.assign]) - that accept const Source&. Per [fs.path.req] paragraph 2:

-2- Functions taking template parameters named Source shall not participate in overload resolution unless either

(2.1) — Source is a specialization of basic_string or basic_string_view, or

(2.2) — the qualified-id iterator_traits<decay_t<Source>>::value_type is valid and denotes a possibly const encoded character type.

iterator_traits<decay_t<path>>::value_type is not valid in C++17, so this specification was sufficient to guard against the conversion constructor template (respectively assignment operator template) "pretending" to be copy constructor (respectively copy assignment operator). P0896R4 "The One Ranges Proposal", however, altered the definition of iterator_traits in the working draft. It now has some convenient default behaviors for types that meet (roughly) the syntax of the Cpp17InputIterator requirements. Notably those requirements include copy construction and copy assignment.

In the working draft, to determine the copyability of std::filesystem::path we must perform overload resolution to determine if we can initialize a path from a constant lvalue of type path. The conversion constructor template that accepts const Source& is a candidate, since its second argument is defaulted, so we must perform template argument deduction to see if this constructor is viable. Source is deduced to path and we then must check the constraint from [fs.path.req] paragraph 2.2 (above). Checking the constraint requires us to specialize iterator_traits<path>, which (per [iterator.traits] paragraph 3.2) requires us to determine if path satisfies the exposition-only cpp17-input-iterator concept, which requires path to be copyable.

We've completed a cycle: determining if path is copyable requires us to first determine if path is copyable. This unfortunate constraint recursion can be broken by explicitly specifying that path is not a valid Source.

History
Date User Action Args
2021-02-25 10:48:01adminsetstatus: wp -> c++20
2019-11-19 14:48:30adminsetstatus: voting -> wp
2019-10-07 02:48:00adminsetstatus: ready -> voting
2019-08-17 17:34:27adminsetmessages: + msg10566
2019-08-17 17:34:27adminsetstatus: new -> ready
2019-08-03 02:10:54adminsetmessages: + msg10533
2019-08-02 00:00:00admincreate