Source in §[fs.path.req] insufficiently constraintySection: 31.12.6.4 [fs.path.req] Status: C++20 Submitter: Casey Carter Opened: 2019-08-02 Last modified: 2021-02-25
Priority: 0
View all issues with C++20 status.
Discussion:
std::filesystem::path has a number of functions - notably including a conversion
constructor template (31.12.6.5.1 [fs.path.construct]) and assignment operator template
(31.12.6.5.2 [fs.path.assign]) - that accept const Source&. Per
31.12.6.4 [fs.path.req] paragraph 2:
-2- Functions taking template parameters named
Sourceshall not participate in overload resolution unless either(2.1) —
Sourceis a specialization ofbasic_stringorbasic_string_view, or(2.2) — the qualified-id
iterator_traits<decay_t<Source>>::value_typeis valid and denotes a possiblyconstencoded 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 31.12.6.4 [fs.path.req]
paragraph 2.2 (above). Checking the constraint requires us to specialize
iterator_traits<path>, which (per 24.3.2.3 [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.
[2019-08-17 Issue Prioritization]
Status to Tentatively Ready and priority to 0 after seven positive votes on the reflector.
Proposed resolution:
This wording is relative to N4830.
Modify 31.12.6.4 [fs.path.req] as indicated:
-2- Functions taking template parameters named
Sourceshall not participate in overload resolution unlessSourcedenotes a type other thanpath, and either[…]