3015. copy_options::unspecified underspecified

Section: [fs.op.copy] Status: New Submitter: Tim Song Opened: 2017-08-24 Last modified: 2017-11-09

Priority: 3

View other active issues in [fs.op.copy].

View all other issues in [fs.op.copy].

View all issues with New status.

Discussion: [fs.op.copy]/4.8.2 says in the copy-a-directory case filesystem::copy performs:

for (const directory_entry& x : directory_iterator(from))
  copy(x.path(), to/x.path().filename(), options | copy_options::unspecified);

Presumably this does not actually mean that the implementation is free to set whatever copy_option element it wishes (directories_only? recursive? create_hard_links?), or none at all, or – since unspecified behavior corresponds to the nondeterministic aspects of the abstract machine (6.8.1 [intro.execution]/3) – a nondeterministically picked element for every iteration of the loop. That would be outright insane.

I'm fairly sure that what's intended here is to set an otherwise-unused bit in options so as to prevent recursion in the options == copy_options::none case.


Priority set to 3 after five votes on the mailing list

Proposed resolution:

This wording is relative to N4687.

  1. Edit [fs.op.copy] p4, bullet 4.8.2 as indicated:

    1. (4.7) — Otherwise, if is_regular_file(f), then:

    2. (4.8) — Otherwise, if

      is_directory(f) &&
      ((options & copy_options::recursive) != copy_options::none ||
      options == copy_options::none)


      1. (4.8.1) — If exists(t) is false, then create_directory(to, from).

      2. (4.8.2) — Then, iterate over the files in from, as if by

        for (const directory_entry& x : directory_iterator(from))
          copy(x.path(), to/x.path().filename(), options | copy_options::unspecifiedin-recursive-copy);

        where in-recursive-copy is an exposition-only bitmask element of copy_options that is not one of the elements in [fs.enum.copy.opts].

    3. (4.9) — Otherwise, for the signature with argument ec, ec.clear().

    4. (4.10) — Otherwise, no effects.