Issue 2250: Follow-up On Library Issue 2207 (original) (raw)


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

2250. Follow-up On Library Issue 2207

Section: 22.9.2.2 [bitset.cons], 22.9.2.3 [bitset.members], 27.4.3.3 [string.cons], 27.4.3.7 [string.modifiers], 27.4.3.8 [string.ops] Status: C++17 Submitter: Frank Birbacher Opened: 2013-04-18 Last modified: 2017-07-30

Priority: 3

View all other issues in [bitset.cons].

View all issues with C++17 status.

Discussion:

Similar to LWG 2207(i) there are several other places where the "Requires" clause precludes the "Throws" condition. Searching for the out_of_range exception to be thrown, the following have been found (based on the working draft N3485):

  1. 22.9.2.2 [bitset.cons] p3+4
  2. 22.9.2.3 [bitset.members] p13+14 (set)
  3. 22.9.2.3 [bitset.members] p19+20 (reset)
  4. 22.9.2.3 [bitset.members] p27+28 (flip)
  5. 22.9.2.3 [bitset.members] p41+42 (test)
  6. 27.4.3.3 [string.cons] p3+4
  7. 27.4.3.7.2 [string.append] p3+4
  8. 27.4.3.7.3 [string.assign] p4+5
  9. 27.4.3.7.4 [string.insert] p1+2, p5+6, p9+10 (partially)
  10. 27.4.3.7.5 [string.erase] p1+2
  11. 27.4.3.7.6 [string.replace] p1+2, p5+6, p9+10 (partially)
  12. 27.4.3.7.7 [string.copy] p1+2
  13. 27.4.3.8.3 [string.substr] p1+2

[2013-10-15: Daniel provides wording]

In addition to the examples mentioned in the discussion, a similar defect exists for thread's join()and detach functions (see 32.4.3.6 [thread.thread.member]). The suggested wording applies a similar fix for these as well.

[2015-05, Lenexa]

STL : likes it
DK : does it change behavior?
Multiple : no
Move to ready? Unanimous

Proposed resolution:

This wording is relative to N3936.

  1. Modify 22.9.2.2 [bitset.cons] as indicated: [Editorial comment: The wording form used to ammend the Throws element is borrowed from a similar style used in 27.4.3.7.6 [string.replace] p10]

    template <class charT, class traits, class Allocator>
    explicit
    bitset(const basic_string<charT, traits, Allocator>& str,
    typename basic_string<charT, traits, Allocator>::size_type pos = 0,

  typename basic_string<charT, traits, Allocator>::size_type n =  
    basic_string<charT, traits, Allocator>::npos,  
    charT zero = charT('0'), charT one = charT('1'));  

-3- Requires: pos <= str.size().

-4- Throws: out_of_range if pos > str.size() or invalid_argument if an invalid character is found (see below).

-5- Effects: Determines the effective length rlen of the initializing string as the smaller of n and str.size() - pos.

The function then throws invalid_argument if any of the rlen characters in str beginning at positionpos is other than zero or one. The function uses traits::eq() to compare the character values.

[…] 2. Modify 22.9.2.3 [bitset.members] as indicated:
bitset& set(size_t pos, bool val = true);

-13- Requires: pos is valid

-14- Throws: out_of_range if pos does not correspond to a valid bit position.

[…]
bitset& reset(size_t pos);

-19- Requires: pos is valid

-20- Throws: out_of_range if pos does not correspond to a valid bit position.

[…]
bitset& flip(size_t pos);

-27- Requires: pos is valid

-28- Throws: out_of_range if pos does not correspond to a valid bit position.

[…]
bool test(size_t pos) const;

-41- Requires: pos is valid

-42- Throws: out_of_range if pos does not correspond to a valid bit position.

[…] 3. Modify 27.4.3.3 [string.cons] as indicated:
basic_string(const basic_string& str,
size_type pos, size_type n = npos,
const Allocator& a = Allocator());

-3- Requires: pos <= str.size()

-4- Throws: out_of_range if pos > str.size(). 4. Modify 27.4.3.5 [string.capacity] as indicated:
void resize(size_type n, charT c);

-6- Requires: n <= max_size()

-7- Throws: length_error if n > max_size(). 5. Modify 27.4.3.7.2 [string.append] as indicated:
basic_string&
append(const basic_string& str, size_type pos, size_type n = npos);

-3- Requires: pos <= str.size()

-4- Throws: out_of_range if pos > str.size(). 6. Modify 27.4.3.7.3 [string.assign] as indicated:
basic_string&
assign(const basic_string& str, size_type pos,
size_type n = npos);

-5- Requires: pos <= str.size()

-6- Throws: out_of_range if pos > str.size(). 7. Modify 27.4.3.7.4 [string.insert] as indicated: [Editorial note: The first change suggestion is also a bug fix of the current wording, because (a) the function has parameter pos1 but the semantics refers to pos and (b) it is possible that this function can throw lengtherror, see p10]
basic_string&
insert(size_type pos1, const basic_string& str);

-1- Requires: pos <= size().

-2- Throws: out_of_range if pos > size().

-3- Effects: CallsEquivalent to: return insert(pos, str.data(), str.size());.

-4- Returns: *this.
basic_string&
insert(size_type pos1, const basic_string& str,
size_type pos2, size_type n = npos);

-5- Requires: pos1 <= size() and pos2 <= str.size().

-6- Throws: out_of_range if pos1 > size() or pos2 > str.size().

[…]
basic_string&
insert(size_type pos, const charT* s, size_type n);

-9- Requires: s points to an array of at least n elements of charT and pos <= size().

-10- Throws: out_of_range if pos > size() or length_error if size() + n > max_size().

[…]
basic_string&
insert(size_type pos, const charT* s);

-13- Requires: pos <= size() and s points to an array of at least traits::length(s) + 1 elements of charT.

-14- Effects: Equivalent to return insert(pos, s, traits::length(s));.

-15- Returns: *this. 8. Modify 27.4.3.7.5 [string.erase] as indicated:
basic_string& erase(size_type pos = 0, size_type n = npos);

-1- Requires: pos <= size()

-2- Throws: out_of_range if pos > size().

[…] 9. Modify 27.4.3.7.6 [string.replace] as indicated: [Editorial note: The first change suggestion is also a bug fix of the current wording, because it is possible that this function can throw lengtherror, see p10]
basic_string&
replace(size_type pos1, size_type n1,
const basic_string& str);

-1- Requires: pos1 <= size().

-2- Throws: out_of_range if pos1 > size().

-3- Effects: CallsEquivalent to return replace(pos1, n1, str.data(), str.size());.

-4- Returns: *this.
basic_string&
replace(size_type pos1, size_type n1,
const basic_string& str,
size_type pos2, size_type n = npos);

-5- Requires: pos1 <= size() and pos2 <= str.size().

-6- Throws: out_of_range if pos1 > size() or pos2 > str.size().

[…]
basic_string&
replace(size_type pos1, size_type n1, const charT* s, size_type n2);

-9- Requires: pos1 <= size() and s points to an array of at least n2 elements of charT.

-10- Throws: out_of_range if pos1 > size() or length_error if the length of the resulting string would exceed max_size() (see below).

[…]
basic_string&
replace(size_type pos, size_type n, const charT* s);

-13- Requires: pos <= size() and s points to an array of at least traits::length(s) + 1 elements of charT.

-14- Effects: Equivalent to return replace(pos, n, s, traits::length(s));.

-15- Returns: *this. 10. Modify 27.4.3.7.7 [string.copy] as indicated:
size_type copy(charT* s, size_type n, size_type pos = 0) const;

-1- Requires: pos <= size()

-2- Throws: out_of_range if pos > size().

[…] 11. Modify 27.4.3.8.3 [string.substr] as indicated:
basic_string substr(size_type pos = 0, size_type n = npos) const;

-1- Requires: pos <= size()

-2- Throws: out_of_range if pos > size().

[…] 12. Modify 32.4.3.6 [thread.thread.member] as indicated:
void join();

-3- Requires: joinable() is true.

[…]

-7- Throws: system_error when an exception is required (30.2.2).

-8- Error conditions:

  • […]
  • invalid_argument — if the thread is not joinable.
    void detach();

-9- Requires: joinable() is true.

[…]

-12- Throws: system_error when an exception is required (30.2.2).

-13- Error conditions:

  • […]
  • invalid_argument — if the thread is not joinable.