2711. path is convertible from approximately everything under the sun

Section: 30.11.7.4.1 [fs.path.construct] Status: C++17 Submitter: Tim Song Opened: 2016-05-10 Last modified: 2017-07-30

Priority: 1

View all issues with C++17 status.

Discussion:

The unconstrained template<class Source> path(const Source& source); constructor defines an implicit conversion from pretty much everything to path. This can lead to surprising ambiguities in overload resolution.

For example, given LWG 2676's proposed resolution, the following code appears to be ambiguous:

struct meow {
  operator const char *() const;
};

std::ifstream purr(meow{});

because a meow can be converted to either a path or a const char* by a user-defined conversion, even though part of the stated goal of LWG 2676's P/R is to avoid "break[ing] user code depending on user-defined automatic conversions to the existing argument types".

Previous resolution [SUPERSEDED]:

This wording is relative to N4582.

[Drafting note: decay_t<Source> handles both the input iterator case (30.11.7.3 [fs.path.req]/1.2) and the array case (30.11.7.3 [fs.path.req]/1.3). The level of constraints required is debatable; the following wording limits the constraint to "is a basic_string or an iterator", but perhaps stronger constraints (e.g., an iterator_category check in the second case, and/or a value_type check for both cases) would be desirable.]

  1. Change 30.11.7.4.1 [fs.path.construct] as indicated:

    template <class Source>
      path(const Source& source);
    template <class InputIterator>
      path(InputIterator first, InputIterator last);
    

    -4- Effects: Constructs an object of class path, storing the effective range of source (27.10.8.3) or the range [first, last) in pathname, converting format and encoding if required (27.10.8.2.1).

    -?- Remarks: The first overload shall not participate in overload resolution unless either Source is a specialization of basic_string or the qualified-id iterator_traits<decay_t<Source>>::value_type is valid and denotes a type (17.9.2 [temp.deduct]).

[2016-05-28, Eric Fiselier comments suggests alternative wording]

Functions taking EcharT or Source parameter types often provide additional overloads with the same arity and concrete types. In order to allow conversions to these concrete types in the interface we need to explicitly disable the EcharT and Source overloads.

[2016-06-19, Eric and Tim improve the wording]

[2016-06, Oulu]

Voted to Ready 8-0 Monday morning in Oulu

Proposed resolution:

This wording is relative to N4594.

[Drafting note: Functions taking EcharT or Source parameter types often provide additional overloads with the same arity and concrete types. In order to allow conversions to these concrete types in the interface we need to explicitly disable the EcharT and Source overloads.]

  1. Change 30.11.4 [fs.req] as indicated:

    -2- Template parameters named EcharT shall beFunctions with template parameters named EcharT shall not participate in overload resolution unless EcharT is one of the encoded character types.

  2. Insert a new paragraph between 30.11.7.3 [fs.path.req] p1 and p2 as indicated:

    -?- Functions taking template parameters named Source shall not participate in overload resolution unless either Source is a specialization of basic_string or the qualified-id iterator_traits<decay_t<Source>>::value_type is valid and denotes a possibly const encoded character type (17.9.2 [temp.deduct]).