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

2989. path's stream insertion operator lets you insert everything under the sun

Section: 28.11.7.6 [fs.path.io] Status: WP Submitter: Billy O'Neal III Opened: 2017-06-27 Last modified: 2018-03-24

Priority: 2

View all issues with WP status.

Discussion:

The rules for converting a path to a narrow character sequence aren't necessarily the same as that iostreams should use. Note that this program creates a temporary path and stream inserts that, which likely destroys information.

#include <iostream>
#include <filesystem>
#include <string>

void foo() {
  using namespace std;
  using namespace std::experimental::filesystem::v1;
  wstring val(L"abc");
  std::cout << val;
}

Using the godbolt online compiler we get:

foo PROC
  sub      rsp, 104   ; 00000068H
  lea      rdx, OFFSET FLAT:$SG44895
  lea      rcx, QWORD PTR val$[rsp]
  call     std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t>
           >::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >
  lea      rdx, QWORD PTR val$[rsp]
  lea      rcx, QWORD PTR $T1[rsp]
  call     ??$?0_WU?$char_traits@_W@std@@V?$allocator@_W@1@@path@v1@filesystem@experimental@std@@QEAA@AEBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@4@@Z
  lea      rdx, QWORD PTR $T1[rsp]
  lea      rcx, OFFSET FLAT:std::cout
  call     std::experimental::filesystem::v1::operator<<<char,std::char_traits<char> >
  lea      rcx, QWORD PTR $T1[rsp]
  call     std::experimental::filesystem::v1::path::~path
  lea      rcx, QWORD PTR val$[rsp]
  call     std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t>
           >::~basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >
  add      rsp, 104   ; 00000068H
  ret      0
foo ENDP

This should either be disabled with a SFINAE constraint, use the auto_ptr user-defined conversion trick, or the stream insertion operators should be made "hidden friends" to prevent conversions to path from being considered here.

[2017-07 Toronto Monday issue prioritization]

Priority 2

[2017-07 Toronto Saturday afternoon]

LWG confirmed they want the hidden friend solution, Billy O'Neal to provide wording.

[2018-1-26 issues processing telecon]

Status to 'Tentatively Ready'

[2018-3-17 Adopted in Jacksonville]

Proposed resolution:

This resolution is relative to N4659.

  1. Edit 28.11.5 [fs.filesystem.syn], header <filesystem> synopsis, as indicated:

    // 28.11.7.6 [fs.path.io], path inserter and extractor
    template <class charT, class traits>
      basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const path& p);
    template <class charT, class traits>
      basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, path& p);
    
  2. Edit 28.11.7.6 [fs.path.io] as indicated:

    [Drafting note: The project editor is kindly asked to consider to move sub-clause 28.11.7.6 [fs.path.io] before sub-clause 28.11.7.7 [fs.path.nonmember] (as a peer of it) — end drafting note]

    template <class charT, class traits>
      friend basic_ostream<charT, traits>&
        operator<<(basic_ostream<charT, traits>& os, const path& p);
    
    […]
    
    template <class charT, class traits>
      friend basic_istream<charT, traits>&
        operator>>(basic_istream<charT, traits>& is, path& p);
    
  3. Edit 28.11.7 [fs.class.path] p2, class path synopsis, as indicated:

    namespace std::filesystem {
      class path {
      public:
        […]
        iterator begin() const;
        iterator end() const;
    
        // 28.11.7.6 [fs.path.io] path inserter and extractor
        template <class charT, class traits>
          friend basic_ostream<charT, traits>&
            operator<<(basic_ostream<charT, traits>& os, const path& p);
        template <class charT, class traits>
          friend basic_istream<charT, traits>&
            operator>>(basic_istream<charT, traits>& is, path& p);
      };
    }