Doc. no. | N4117
Date: | 2014-07-08
Project: | Programming Language C++
Reply to: | Alisdair Meredith <lwgchair@gmail.com>

# C++ Standard Library Active Issues List (Revision R89)

Revised 2014-07-08 at 16:07:00 UTC

Reference ISO/IEC IS 14882:2011(E)

Also see:

- Table of Contents for all library issues.
- Index by Section for all library issues.
- Index by Status for all library issues.
- Library Defect Reports List
- Library Closed Issues List

The purpose of this document is to record the status of issues which have come before the Library Working Group (LWG) of the INCITS PL22.16 and ISO WG21 C++ Standards Committee. Issues represent potential defects in the ISO/IEC IS 14882:2011(E) document.

This document contains only library issues which are actively being considered by the Library Working Group, i.e., issues which have a status of New, Open, Ready, or Review. See Library Defect Reports List for issues considered defects and Library Closed Issues List for issues considered closed.

The issues in these lists are not necessarily formal ISO Defect Reports (DR's). While some issues will eventually be elevated to official Defect Report status, other issues will be disposed of in other ways. See Issue Status.

Prior to Revision 14, library issues lists existed in two slightly different versions; a Committee Version and a Public Version. Beginning with Revision 14 the two versions were combined into a single version.

This document includes [bracketed italicized notes] as a reminder to the LWG of current progress on issues. Such notes are strictly unofficial and should be read with caution as they may be incomplete or incorrect. Be aware that LWG support for a particular resolution can quickly change if new viewpoints or killer examples are presented in subsequent discussions.

For the most current official version of this document see http://www.open-std.org/jtc1/sc22/wg21/. Requests for further information about this document should include the document number above, reference ISO/IEC 14882:2011(E), and be submitted to Information Technology Industry Council (ITI), 1250 Eye Street NW, Washington, DC 20005.

Public information as to how to obtain a copy of the C++ Standard, join the standards committee, submit an issue, or comment on an issue can be found in the comp.std.c++ FAQ.

How to submit an issue

1. Mail your issue to the author of this list.
2. Specify a short descriptive title. If you fail to do so, the subject line of your mail will be used as the issue title.
3. If the "From" on your email is not the name you wish to appear as issue submitter, then specify issue submitter.
4. Provide a brief discussion of the problem you wish to correct. Refer to the latest working draft or standard using [section.tag] and paragraph numbers where appropriate.
5. Provide proposed wording. This should indicate exactly how you want the standard to be changed. General solution statements belong in the discussion area. This area contains very clear and specific directions on how to modify the current draft. If you are not sure how to word a solution, you may omit this part. But your chances of a successful issue greatly increase if you attempt wording.
6. It is not necessary for you to use html markup. However, if you want to, you can <ins>insert text like this</ins> and <del>delete text like this</del>. The only strict requirement is to communicate clearly to the list maintainer exactly how you want your issue to look.
7. It is not necessary for you to specify other html font/formatting mark-up, but if you do the list maintainer will attempt to respect your formatting wishes (as described by html markup, or other common idioms).
8. It is not necessary for you to specify open date or last modified date (the date of your mail will be used).
9. It is not necessary for you to cross reference other issues, but you can if you like. You do not need to form the hyperlinks when you do, the list maintainer will take care of that.
10. One issue per email is best.
11. Between the time you submit the issue, and the next mailing deadline (date at the top of the Revision History), you own this issue. You control the content, the stuff that is right, the stuff that is wrong, the format, the misspellings, etc. You can even make the issue disappear if you want. Just let the list maintainer know how you want it to look, and he will try his best to accommodate you. After the issue appears in an official mailing, you no longer enjoy exclusive ownership of it.

## Revision History

- R89: 2014-07-08 post-Rapperswil mailing
  - Summary:
    - 196 open issues, up by 14.
    - 1742 closed issues, up by 12.
    - 1938 issues total, up by 26.
  - Details:
    - Added the following 6 Ready issues: 2396, 2399, 2400, 2401, 2404, 2408.
    - Added the following 15 New issues: 2391, 2392, 2393, 2394, 2398, 2402, 2403, 2406, 2407, 2410, 2411, 2412, 2413, 2414, 2415.
    - Added the following Open issue: 2397.
    - Added the following 3 WP issues: 2390, 2395, 2409.
    - Added the following NAD issue: 2405.
    - Changed the following issue to Ready (from New): 2377.
    - Changed the following 2 issues to Ready (from Deferred): 2253, 2255.
    - Changed the following 2 issues to Tentatively Ready (from New): 2325, 2387.
    - Changed the following issue to Tentatively NAD (from New): 2382.
    - Changed the following 3 issues to Review (from New): 2364, 2378, 2380.
    - Changed the following 2 issues to Review (from Open): 2118, 2160.
    - Changed the following 3 issues to Open (from New): 2168, 2238, 2273.
    - Changed the following 3 issues to Open (from Deferred): 2254, 2264, 2277.
    - Changed the following 3 issues to WP (from New): 2371, 2374, 2389.
    - Changed the following 4 issues to Resolved (from Deferred): 2282, 2283, 2287, 2333.
    - Changed the following issue to NAD (from Deferred): 2305.
- R88: 2014-05-24 pre-Rapperswil mailing
  - Summary:
    - 182 open issues, up by 29.
    - 1730 closed issues, up by 0.
    - 1912 issues total, up by 29.
  - Details:
    - Added the following 3 Tentatively Ready issues: 2361, 2365, 2376.
    - Added the following 26 New issues: 2362, 2363, 2364, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389.
    - Changed the following 5 issues to Tentatively Ready (from Open): 2106, 2129, 2212, 2230, 2233.
- R87: 2014-03-03 post-Issaquah mailing
  - Summary:
    - 153 open issues, down by 60.
    - 1730 closed issues, up by 65.
    - 1883 issues total, up by 5.
  - Details:
    - Added the following New issue: 2358.
    - Added the following 4 C++14 issues: 2356, 2357, 2359, 2360.
    - Changed the following issue to Ready (from Review): 2170.
    - Changed the following 3 issues to Ready (from New): 2319, 2340, 2354.
    - Changed the following issue to Ready (from Open): 2016.
    - Changed the following 2 issues to Tentatively Ready (from New): 2217, 2266.
    - Changed the following issue to Tentatively NAD (from New): 2302.
    - Changed the following issue to Review (from Open): 2111.
    - Changed the following issue to New (from Open): 2117.
    - Changed the following 4 issues to Open (from New): 2241, 2321, 2328, 2331.
    - Changed the following 5 issues to Open (from Deferred): 1213, 2095, 2139, 2202, 2230.
    - Changed the following 3 issues to Pending NAD Editorial (from Tentatively NAD Editorial): 2125, 2126, 2134.
    - Changed the following 11 issues to C++14 (from Ready): 2135, 2142, 2252, 2257, 2268, 2271, 2272, 2278, 2280, 2285, 2291.
    - Changed the following 3 issues to C++14 (from Review): 2132, 2182, 2299.
    - Changed the following 28 issues to C++14 (from New): 2104, 2205, 2213, 2258, 2263, 2288, 2293, 2301, 2304, 2306, 2308, 2313, 2314, 2315, 2316, 2317, 2320, 2322, 2323, 2324, 2329, 2330, 2332, 2339, 2341, 2344, 2346, 2350.
    - Changed the following 5 issues to C++14 (from Open): 1450, 2003, 2112, 2186, 2188.
    - Changed the following issue to C++14 (from EWG): 2193.
    - Changed the following 97 issues to C++14 (from WP): 1214, 2005, 2009, 2010, 2011, 2013, 2015, 2018, 2021, 2028, 2033, 2039, 2044, 2045, 2047, 2048, 2049, 2050, 2053, 2056, 2058, 2061, 2064, 2065, 2067, 2069, 2071, 2074, 2078, 2080, 2081, 2083, 2085, 2086, 2087, 2091, 2092, 2093, 2094, 2096, 2097, 2098, 2099, 2100, 2102, 2103, 2105, 2109, 2110, 2120, 2122, 2123, 2128, 2130, 2138, 2140, 2141, 2143, 2144, 2145, 2147, 2148, 2149, 2150, 2159, 2162, 2163, 2169, 2172, 2174, 2175, 2176, 2177, 2180, 2185, 2187, 2190, 2194, 2196, 2197, 2200, 2203, 2207, 2209, 2210, 2211, 2222, 2225, 2229, 2231, 2235, 2246, 2247, 2275, 2284, 2298, 2300.
    - Changed the following issue to Resolved (from Ready): 2240.
    - Changed the following 2 issues to Resolved (from Open): 2052, 2075.
    - Changed the following issue to NAD Editorial (from Pending NAD Editorial): 2281.
    - Changed the following 2 issues to NAD (from Tentatively NAD): 2131, 2204.
    - Changed the following 5 issues to NAD (from New): 2311, 2327, 2345, 2347, 2355.
    - Changed the following issue to NAD (from Pending NAD): 2046.
- R86: 2014-01-20 pre-Issaquah mailing
  - Summary:
    - 213 open issues, up by 18.
    - 1665 closed issues, up by 0.
    - 1878 issues total, up by 18.
  - Details:
    - Added the following 18 New issues: 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355.
    - Changed the following 4 issues to Ready (from New): 2268, 2271, 2280, 2285.
    - Changed the following 5 issues to Open (from New): 2192, 2195, 2260, 2274, 2294.
    - Changed the following 2 issues to Deferred (from New): 2202, 2230.
- R85: 2013-10 post-Chicago mailing
  - Summary:
    - 195 open issues, up by 22.
    - 1665 closed issues, up by 28.
    - 1860 issues total, up by 50.
  - Details:
    - Added the following Ready issue: 2291.
    - Added the following Review issue: 2299.
    - Added the following 43 New issues: 2288, 2289, 2290, 2292, 2293, 2294, 2295, 2296, 2301, 2302, 2303, 2304, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2334, 2335, 2336, 2337.
    - Added the following 2 Deferred issues: 2305, 2333.
    - Added the following 2 WP issues: 2298, 2300.
    - Added the following NAD issue: 2297.
    - Changed the following 5 issues to Ready (from New): 2240, 2252, 2257, 2272, 2278.
    - Changed the following 2 issues to Ready (from Open): 2135, 2142.
    - Changed the following issue to Review (from Core): 2170.
    - Changed the following 9 issues to Deferred (from New): 2095, 2253, 2254, 2255, 2264, 2277, 2282, 2283, 2287.
    - Changed the following issue to Pending NAD Editorial (from New): 2281.
    - Changed the following issue to NAD Future (from Open): 2232.
    - Changed the following 4 issues to WP (from Ready): 2141, 2235, 2246, 2247.
    - Changed the following 6 issues to WP (from Tentatively Ready): 2085, 2087, 2143, 2150, 2180, 2194.
    - Changed the following issue to WP (from Tentatively NAD Editorial): 2078.
    - Changed the following 3 issues to WP (from Review): 2013, 2100, 2120.
    - Changed the following 3 issues to WP (from New): 2097, 2275, 2284.
    - Changed the following 2 issues to WP (from Open): 2018, 2159.
    - Changed the following issue to Resolved (from New): 2249.
    - Changed the following issue to NAD (from Tentatively NAD): 2167.
    - Changed the following 2 issues to NAD (from New): 2270, 2279.
- R84: 2013-09 pre-Chicago mailing
  - Summary:
    - 173 open issues, up by 36.
    - 1637 closed issues, up by 0.
    - 1810 issues total, up by 36.
  - Details:
    - Added the following 36 New issues: 2252, 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287.
    - Changed the following 6 issues to Tentatively Ready (from New): 2085, 2087, 2143, 2150, 2180, 2194.
    - Changed the following 2 issues to Tentatively NAD (from New): 2131, 2204.
    - Changed the following 3 issues to Open (from New): 2181, 2188, 2214.
- R83: 2013-05 post-Bristol mailing
  - Summary:
    - 137 open issues, down by 37.
    - 1637 closed issues, up by 40.
    - 1774 issues total, up by 3.
  - Details:
    - Added the following 3 New issues: 2249, 2250, 2251.
    - Changed the following 2 issues to Ready (from Review): 2141, 2235.
    - Changed the following 2 issues to Ready (from New): 2246, 2247.
    - Changed the following 3 issues to Open (from Review): 2219, 2223, 2227.
    - Changed the following 8 issues to WP (from Ready): 2091, 2092, 2093, 2145, 2147, 2163, 2169, 2172.
    - Changed the following 14 issues to WP (from Tentatively Ready): 2080, 2109, 2144, 2174, 2175, 2177, 2187, 2197, 2200, 2209, 2211, 2222, 2225, 2231.
    - Changed the following 14 issues to WP (from Review): 2094, 2098, 2130, 2138, 2140, 2162, 2176, 2185, 2190, 2196, 2203, 2207, 2210, 2229.
    - Changed the following 4 issues to WP (from Open): 2122, 2128, 2148, 2149.
- R82: 2013-03 pre-Bristol mailing
  - Summary:
    - 174 open issues, up by 13.
    - 1597 closed issues, up by 1.
    - 1771 issues total, up by 14.
  - Details:
    - Added the following Review issue: 2235.
    - Added the following 13 New issues: 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248.
    - Changed the following 10 issues to Tentatively Ready (from New): 2144, 2174, 2175, 2197, 2200, 2209, 2211, 2222, 2225, 2231.
    - Changed the following 11 issues to Review (from New): 2141, 2176, 2182, 2203, 2207, 2210, 2219, 2223, 2227, 2228, 2229.
    - Changed the following 19 issues to Open (from New): 2133, 2146, 2151, 2153, 2155, 2156, 2160, 2179, 2189, 2198, 2199, 2206, 2212, 2215, 2218, 2224, 2232, 2233, 2234.
    - Changed the following issue to NAD Future (from New): 2226.
- R81: 2013-01 mid-term mailing
  - Summary:
    - 161 open issues, up by 21.
    - 1596 closed issues, up by 3.
    - 1757 issues total, up by 24.
  - Details:
    - Added the following 24 New issues: 2211, 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234.
    - Changed the following issue to Open (from Tentatively Ready): 2106.
    - Changed the following 3 issues to Resolved (from Open): 2012, 2054, 2057.
- R80: 2012-11-02 post-Portland mailing
  - Summary:
    - 140 open issues, up by 4.
    - 1593 closed issues, up by 17.
    - 1733 issues total, up by 21.
  - Details:
    - Added the following 2 Review issues: 2190, 2196.
    - Added the following 18 New issues: 2191, 2192, 2194, 2195, 2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210.
    - Added the following EWG issue: 2193.
    - Changed the following 3 issues to Ready (from Review): 2091, 2092, 2093.
    - Changed the following 5 issues to Ready (from New): 2145, 2147, 2163, 2169, 2172.
    - Changed the following 3 issues to Tentatively Ready (from Review): 2080, 2106, 2109.
    - Changed the following 2 issues to Tentatively Ready (from New): 2177, 2187.
    - Changed the following 4 issues to Tentatively NAD Editorial (from New): 2078, 2125, 2126, 2134.
    - Changed the following issue to Tentatively NAD (from New): 2167.
    - Changed the following 9 issues to Review (from New): 2098, 2100, 2120, 2130, 2132, 2138, 2140, 2162, 2185.
    - Changed the following issue to Open (from Review): 1175.
    - Changed the following 12 issues to Open (from New): 2075, 2135, 2136, 2137, 2142, 2148, 2149, 2152, 2157, 2159, 2178, 2186.
    - Changed the following issue to Open (from NAD Future): 2051.
    - Changed the following 2 issues to Core (from New): 2165, 2170.
    - Changed the following issue to Deferred (from New): 2139.
    - Changed the following 10 issues to WP (from Ready): 2071, 2074, 2081, 2083, 2086, 2099, 2103, 2105, 2110, 2123.
    - Changed the following 6 issues to WP (from Tentatively Ready): 2005, 2011, 2048, 2049, 2056, 2058.
    - Changed the following issue to NAD (from Tentatively NAD): 2124.
    - Changed the following issue to NAD (from New): 2171.
- R79: 2012-09-24 pre-Portland mailing
  - Summary:
    - 136 open issues, up by 60.
    - 1576 closed issues, up by 0.
    - 1712 issues total, up by 60.
  - Details:
    - Added the following 60 New issues: 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189.
    - No issues changed.
- R78: 2012-02-27 post-Kona mailing
  - Summary:
    - 76 open issues, down by 20.
    - 1576 closed issues, up by 26.
    - 1652 issues total, up by 6.
  - Details:
    - Added the following 2 New issues: 2125, 2126.
    - Added the following 3 Open issues: 2127, 2128, 2129.
    - Added the following Tentatively NAD issue: 2124.
    - Changed the following 5 issues from New to NAD: 2073, 2082, 2090, 2107, 2113.
    - Changed the following issue from Pending NAD Editorial to NAD Editorial: 2060.
    - Changed the following issue from Deferred to Open: 1526.
    - Changed the following 15 issues from New to Open: 2072, 2077, 2088, 2089, 2101, 2108, 2111, 2112, 2114, 2115, 2116, 2117, 2118, 2119, 2122.
    - Changed the following 2 issues from Review to Open: 1169, 2059.
    - Changed the following 10 issues from New to Ready: 2071, 2074, 2081, 2083, 2086, 2099, 2103, 2105, 2110, 2123.
    - Changed the following issue from Tentatively Resolved to Resolved: 2066.
    - Changed the following 7 issues from New to Review: 2080, 2091, 2092, 2093, 2094, 2106, 2109.
    - Changed the following issue from Ready to Review: 2013.
    - Changed the following 6 issues from Review to Tentatively Ready: 2005, 2011, 2048, 2049, 2056, 2058.
    - Changed the following 18 issues from Ready to WP: 1214, 2009, 2010, 2015, 2021, 2028, 2033, 2039, 2044, 2045, 2047, 2050, 2053, 2061, 2064, 2065, 2067, 2069.
    - Changed the following 2 issues from Tentatively Ready to WP: 2096, 2102.
- R77: 2012-01-16 pre-Kona mailing
  - Summary:
    - 96 open issues, up by 52.
    - 1550 closed issues, up by 1.
    - 1646 issues total, up by 53.
  - Details:
    - Added the following NAD issue: 2084.
    - Added the following 50 New issues: 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2097, 2098, 2099, 2100, 2101, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123.
    - Added the following 2 Tentatively Ready issues: 2096, 2102.
    - No issues changed.
- R76: 2011-09-06 post-Bloomington mailing
  - Summary:
    - 44 open issues, up by 19.
    - 1549 closed issues, up by 9.
    - 1593 issues total, up by 28.
  - Details:
    - Added the following 2 NAD issues: 2043, 2068.
    - Added the following 2 NAD Future issues: 2051, 2055.
    - Added the following 6 Open issues: 2052, 2054, 2057, 2062, 2063, 2070.
    - Added the following Pending NAD issue: 2046.
    - Added the following Pending NAD Editorial issue: 2060.
    - Added the following 10 Ready issues: 2044, 2045, 2047, 2050, 2053, 2061, 2064, 2065, 2067, 2069.
    - Added the following 5 Review issues: 2048, 2049, 2056, 2058, 2059.
    - Added the following Tentatively Resolved issue: 2066.
    - Changed the following 322 issues from WP to C++11: 149, 296, 419, 427, 430, 471, 473, 498, 539, 556, 564, 565, 630, 659, 671, 676, 688, 696, 704, 711, 716, 723, 724, 727, 752, 753, 758, 765, 774, 780, 788, 810, 811, 814, 817, 819, 821, 835, 836, 838, 847, 853, 854, 857, 859, 860, 861, 865, 866, 868, 869, 870, 871, 872, 876, 878, 881, 883, 885, 886, 888, 890, 891, 893, 894, 896, 898, 899, 900, 904, 907, 909, 911, 920, 921, 922, 925, 929, 931, 934, 938, 939, 943, 948, 949, 951, 954, 956, 957, 960, 962, 963, 965, 967, 968, 970, 974, 975, 978, 981, 982, 984, 986, 987, 990, 991, 993, 994, 997, 998, 999, 1004, 1006, 1011, 1012, 1014, 1019, 1021, 1030, 1033, 1034, 1037, 1038, 1039, 1040, 1044, 1045, 1065, 1066, 1070, 1071, 1073, 1079, 1089, 1094, 1095, 1097, 1098, 1103, 1104, 1108, 1110, 1113, 1114, 1118, 1123, 1126, 1130, 1131, 1133, 1134, 1136, 1137, 1138, 1144, 1152, 1157, 1158, 1159, 1170, 1171, 1177, 1178, 1180, 1181, 1182, 1183, 1187, 1189, 1191, 1192, 1193, 1194, 1195, 1197, 1198, 1199, 1204, 1205, 1206, 1207, 1208, 1209, 1215, 1216, 1218, 1220, 1221, 1222, 1227, 1231, 1234, 1237, 1240, 1241, 1245, 1247, 1249, 1250, 1252, 1253, 1254, 1255, 1256, 1257, 1261, 1262, 1264, 1267, 1270, 1271, 1276, 1277, 1278, 1279, 1280, 1284, 1285, 1286, 1287, 1288, 1292, 1294, 1295, 1298, 1299, 1303, 1306, 1309, 1310, 1312, 1316, 1319, 1323, 1325, 1332, 1333, 1334, 1335, 1337, 1338, 1339, 1340, 1349, 1354, 1360, 1362, 1363, 1367, 1368, 1370, 1372, 1381, 1384, 1385, 1386, 1387, 1388, 1399, 1400, 1401, 1402, 1403, 1404, 1408, 1414, 1416, 1417, 1418, 1420, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1448, 1449, 1474, 1478, 1479, 1480, 1487, 1494, 1497, 1514, 1516, 1517, 1518, 1519, 1520, 1522, 1524, 1525, 2000, 2001, 2004, 2007, 2008, 2014, 2017, 2019, 2020, 2022, 2027, 2029, 2030, 2031, 2032, 2041, 2042.
    - Changed the following issue from Deferred to NAD: 1330.
    - Changed the following issue from Deferred to NAD Future: 1521.
    - Changed the following issue from Open to NAD Future: 2040.
    - Changed the following issue from Deferred to Open: 1450.
    - Changed the following issue from Deferred to Ready: 1214.
    - Changed the following 2 issues from New to Ready: 2013, 2015.
    - Changed the following 2 issues from Open to Ready: 2010, 2033.
    - Changed the following issue from Review to Ready: 2021.
    - Changed the following 2 issues from Deferred to Review: 1169, 1175.
    - Changed the following issue from Open to Review: 2011.
- R75: 2011-03-28 post-Madrid mailing
  - Summary:
    - 25 open issues, down by 71.
    - 1540 closed issues, up by 80.
    - 1565 issues total, up by 9.
  - Details:
    - Added the following NAD issue: 2036.
    - Added the following 2 Open issues: 2038, 2040.
    - Added the following Ready issue: 2039.
    - Added the following Resolved issue: 2037.
    - Added the following 2 WP issues: 2041, 2042.
    - Changed the following issue from New to Deferred: 1521.
    - Changed the following 2 issues from Open to Deferred: 1169, 1175.
    - Changed the following 7 issues from Open to NAD: 1318, 1348, 1358, 1369, 1374, 1452, 1461.
    - Changed the following 6 issues from Tentatively NAD to NAD: 1371, 1413, 1485, 1486, 2006, 2026.
    - Changed the following issue from Tentatively Ready to NAD: 1456.
    - Changed the following 2 issues from Open to NAD Future: 1396, 1459.
    - Changed the following issue from Tentatively NAD Future to NAD Future: 1320.
    - Changed the following 4 issues from New to Open: 2012, 2018, 2033, 2035.
    - Changed the following issue from New to Ready: 2028.
    - Changed the following issue from Review to Ready: 2009.
    - Changed the following issue from NAD to Resolved: 343.
    - Changed the following issue from NAD Editorial to Resolved: 485.
    - Changed the following 3 issues from New to Resolved: 1523, 2025, 2034.
    - Changed the following 13 issues from Open to Resolved: 964, 966, 985, 1297, 1345, 1353, 1364, 1421, 1460, 1502, 1504, 1505, 1507.
    - Changed the following 4 issues from Tentatively Ready to Resolved: 1457, 1515, 2023, 2024.
    - Changed the following issue from New to Review: 2021.
    - Changed the following issue from Open to Review: 2005.
    - Changed the following 3 issues from New to WP: 1524, 2008, 2032.
    - Changed the following 5 issues from Open to WP: 1252, 1349, 1448, 1478, 1487.
    - Changed the following 8 issues from Ready to WP: 1279, 1332, 1385, 1401, 1408, 1418, 1420, 1438.
    - Changed the following 22 issues from Tentatively Ready to WP: 1215, 1253, 1310, 1474, 1479, 1480, 1494, 1497, 1514, 2000, 2001, 2004, 2007, 2014, 2017, 2019, 2020, 2022, 2027, 2029, 2030, 2031.
- R74: 2011-02-28 pre-Madrid mailing
  - Summary:
    - 96 open issues, up by 16.
    - 1460 closed issues, up by 1.
    - 1556 issues total, up by 17.
  - Details:
    - Added the following 7 New issues: 2021, 2025, 2028, 2032, 2033, 2034, 2035.
    - Added the following Tentatively NAD issue: 2026.
    - Added the following 8 Tentatively Ready issues: 2020, 2022, 2023, 2024, 2027, 2029, 2030, 2031.
    - Changed the following issue from Open to NAD Editorial: 1503.
    - Changed the following issue from New to Open: 2016.
    - Changed the following issue from Ready to Open: 1318.
    - Changed the following issue from NAD to Resolved: 1229.
    - Changed the following 65 issues from NAD Editorial to Resolved: 732, 756, 767, 793, 794, 800, 803, 825, 828, 874, 875, 880, 889, 897, 908, 923, 924, 940, 944, 958, 976, 1043, 1046, 1047, 1048, 1049, 1050, 1088, 1090, 1093, 1106, 1129, 1143, 1145, 1146, 1147, 1160, 1161, 1162, 1163, 1165, 1166, 1172, 1185, 1196, 1210, 1211, 1212, 1225, 1226, 1244, 1248, 1266, 1269, 1272, 1273, 1274, 1275, 1281, 1291, 1300, 1304, 1305, 1311, 1329.
    - Changed the following 2 issues from Open to Tentatively NAD: 1485, 1486.
    - Changed the following 3 issues from New to Tentatively Ready: 2014, 2017, 2019.
    - Changed the following 8 issues from Open to Tentatively Ready: 1456, 1457, 1474, 1479, 1494, 1514, 1515, 2001.
    - Changed the following issue from Review to Tentatively Ready: 1480.
- R73: 2010-11-29 Post-Batavia mailing.
  - Summary:
    - 80 open issues, down by 126.
    - 1459 closed issues, up by 145.
    - 1539 issues total, up by 19.
  - Details:
    - Added the following 11 New issues: 1521, 1523, 2008, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019.
    - Added the following 5 Open issues: 2001, 2003, 2005, 2010, 2011.
    - Added the following Resolved issue: 2002.
    - Added the following Review issue: 2009.
    - Added the following Tentatively NAD issue: 2006.
    - Added the following 3 Tentatively Ready issues: 2000, 2004, 2007.
    - Added the following WP issue: 1522.
    - Changed the following 3 issues from New to Deferred: 1213, 1214, 1330.
    - Changed the following issue from Open to Deferred: 1450.
    - Changed the following 14 issues from Open to Dup: 1350, 1351, 1352, 1375, 1411, 1443, 1451, 1454, 1458, 1463, 1470, 1475, 1476, 1477.
    - Changed the following issue from New to NAD: 1331.
    - Changed the following 8 issues from Open to NAD: 579, 1359, 1361, 1373, 1376, 1398, 1446, 1473.
    - Changed the following 2 issues from Tentatively NAD to NAD: 1190, 1200.
    - Changed the following issue from WP to NAD: 822.
    - Changed the following 11 issues from Open to NAD Editorial: 1395, 1442, 1471, 1472, 1489, 1495, 1496, 1509, 1510, 1511, 1512.
    - Changed the following issue from Review to NAD Editorial: 1281.
    - Changed the following issue from New to NAD Future: 1289.
    - Changed the following 6 issues from Open to NAD Future: 1406, 1422, 1484, 1488, 1493, 1499.
    - Changed the following 2 issues from Tentatively NAD Future to NAD Future: 1173, 1188.
    - Changed the following 2 issues from New to Open: 1252, 1297.
    - Changed the following 3 issues from New to Ready: 1279, 1318, 1332.
    - Changed the following 6 issues from Open to Ready: 1385, 1401, 1408, 1418, 1420, 1438.
    - Changed the following 42 issues from NAD Editorial to Resolved: 353, 431, 482, 525, 594, 625, 635, 658, 697, 719, 742, 786, 815, 816, 823, 827, 834, 884, 932, 947, 950, 953, 983, 1054, 1055, 1075, 1100, 1116, 1117, 1122, 1135, 1151, 1174, 1258, 1260, 1283, 1293, 1307, 1321, 1394, 1405, 1407.
    - Changed the following 5 issues from New to Resolved: 1290, 1322, 1324, 1326, 1328.
    - Changed the following 46 issues from Open to Resolved: 801, 1268, 1327, 1344, 1346, 1347, 1355, 1356, 1357, 1365, 1366, 1377, 1378, 1379, 1380, 1382, 1383, 1389, 1390, 1391, 1392, 1393, 1397, 1409, 1410, 1412, 1445, 1447, 1453, 1455, 1462, 1464, 1465, 1466, 1467, 1468, 1469, 1481, 1482, 1490, 1491, 1492, 1498, 1501, 1508, 1513.
    - Changed the following issue from Open to Review: 1480.
    - Changed the following 2 issues from Open to Tentatively NAD: 1371, 1413.
    - Changed the following issue from New to Tentatively NAD Future: 1320.
    - Changed the following 3 issues from New to Tentatively Ready: 1215, 1253, 1310.
    - Changed the following issue from Open to Tentatively Ready: 1497.
    - Changed the following 24 issues from NAD Editorial to WP: 1360, 1363, 1367, 1372, 1381, 1384, 1386, 1387, 1388, 1399, 1400, 1402, 1403, 1416, 1417, 1423, 1424, 1425, 1426, 1427, 1429, 1430, 1431, 1441.
    - Changed the following issue from New to WP: 1294.
    - Changed the following 10 issues from Open to WP: 1354, 1362, 1368, 1370, 1428, 1435, 1436, 1437, 1439, 1440.
    - Changed the following 2 issues from Ready to WP: 868, 951.
    - Changed the following 33 issues from Tentatively Ready to WP: 956, 1118, 1171, 1181, 1183, 1191, 1198, 1207, 1234, 1240, 1249, 1292, 1295, 1316, 1319, 1323, 1325, 1333, 1334, 1335, 1337, 1338, 1339, 1340, 1404, 1414, 1432, 1449, 1516, 1517, 1518, 1519, 1520.
- R72: 2010-10-18 pre-Batavia mailing.
  - Summary:
    - 206 open issues, up by 141.
    - 1314 closed issues, up by 36.
    - 1520 issues total, up by 177.
  - Details:
    - Added the following Dup issues: 1433, 1444.
    - Added the following NAD Editorial issues: 1360, 1363, 1367, 1372, 1381, 1384, 1386, 1387, 1388, 1394, 1399, 1400, 1402, 1403, 1405, 1407, 1415, 1416, 1417, 1419, 1423, 1424, 1425, 1426, 1427, 1429, 1430, 1431, 1434, 1441, 1483, 1500, 1506.
    - Added the following Open issues: 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1361, 1362, 1364, 1365, 1366, 1368, 1369, 1370, 1371, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1382, 1383, 1385, 1389, 1390, 1391, 1392, 1393, 1395, 1396, 1397, 1398, 1401, 1406, 1408, 1409, 1410, 1411, 1412, 1413, 1418, 1420, 1421, 1422, 1428, 1435, 1436, 1437, 1438, 1439, 1440, 1442, 1443, 1445, 1446, 1447, 1448, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1501, 1502, 1503, 1504, 1505, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515.
    - Added the following Tentatively Ready issues: 1404, 1414, 1432, 1449, 1516, 1517, 1518, 1519, 1520.
    - Changed the following issues from New to NAD Editorial: 1260.
    - Changed the following issues from New to Tentatively Ready: 1181, 1240, 1249, 1292, 1295, 1316, 1319, 1323, 1325, 1333, 1334, 1335, 1337, 1338, 1339, 1340.
    - Changed the following issues from Open to Tentatively Ready: 956, 1118, 1183, 1234.
- R71: 2010-08-25 post-Rapperswil mailing.
  - Summary:
    - 65 open issues, up by 2.
    - 1278 closed issues, up by 7.
    - 1343 issues total, up by 9.
  - Details:
    - Added the following New issues: 1335, 2008, 1337, 1338, 1339, 1340, 2009, 2010, 2011.
    - Changed the following issues from Open to NAD: 996, 1119.
    - Changed the following issues from Open to NAD Concepts: 1076.
    - Changed the following issues from Open to NAD Editorial: 953.
    - Changed the following issues from New to Open: 1169, 1175.
    - Changed the following issues from Open to Ready: 951.
    - Changed the following issues from Review to Ready: 868.
    - Changed the following issues from New to Tentatively NAD: 1190, 1200.
    - Changed the following issues from New to Tentatively NAD Future: 1188.
    - Changed the following issues from Open to Tentatively NAD Future: 1173.
    - Changed the following issues from New to Tentatively Ready: 1198.
    - Changed the following issues from Open to Tentatively Ready: 1171, 1191, 1207.
    - Changed the following issues from Ready to WP: 1187, 1206, 1278.
- R70: 2010-03-26 post-Pittsburgh mailing.
  - Summary:
    - 63 open issues, down by 203.
    - 1271 closed issues, up by 219.
    - 1334 issues total, up by 16.
  - Details:
    - Added the following NAD Editorial issues: 1321, 1329.
    - Added the following New issues: 1319, 1320, 1322, 1323, 1324, 1325, 1326, 1328, 1330, 1331, 1332, 1333, 1334.
    - Added the following Open issues: 1327.
    - Changed the following issues from Tentatively Dup to Dup: 1219.
    - Changed the following issues from New to NAD: 1302, 1308, 1313, 1314.
    - Changed the following issues from Open to NAD: 887, 1008, 1068, 1069, 1153, 1156, 1228.
    - Changed the following issues from Tentatively NAD to NAD: 631, 726, 959, 1056, 1099, 1125, 1176, 1202, 1223, 1224, 1246, 1251, 1259, 1263, 1265, 1296.
    - Changed the following issues from Tentatively NAD Concepts to NAD Concepts: 910, 1186.
    - Changed the following issues from New to NAD Editorial: 1185, 1210, 1212, 1225, 1244, 1266, 1269, 1272, 1275, 1291, 1305, 1307, 1311.
    - Changed the following issues from Open to NAD Editorial: 299, 397, 408, 446, 594, 625, 742, 834, 915, 1093, 1151, 1211, 1248.
    - Changed the following issues from Ready to NAD Editorial: 485, 932, 940, 950, 983, 1100, 1135.
    - Changed the following issues from Tentatively NAD Editorial to NAD Editorial: 815, 816, 889, 1106, 1115, 1233, 1239, 1258, 1283, 1301.
    - Changed the following issues from Tentatively Ready to NAD Editorial: 1090, 1226, 1273, 1274, 1293, 1300, 1304, 1315.
    - Changed the following issues from New to NAD Future: 1154, 1317.
    - Changed the following issues from Ready to NAD Future: 1052.
    - Changed the following issues from Tentatively NAD Future to NAD Future: 1112, 1121, 1201, 1238, 1282.
    - Changed the following issues from New to Open: 1234, 1268.
    - Changed the following issues from Tentatively Ready to Open: 579.
    - Changed the following issues from New to Ready: 1187, 1206, 1278.
    - Changed the following issues from New to Review: 1281.
    - Changed the following issues from Ready to Review: 868.
    - Changed the following issues from New to WP: 1159.
    - Changed the following issues from Open to WP: 427, 430, 774, 819, 835, 861, 885, 896, 900, 911, 1079.
    - Changed the following issues from Ready to WP: 296, 471, 473, 539, 671, 836, 854, 860, 865, 871, 872, 920, 921, 939, 954, 957, 960, 962, 963, 967, 968, 974, 1011, 1030, 1094, 1095, 1097, 1098, 1104, 1123, 1134, 1136, 1144, 1157, 1194, 1204, 1216, 1227, 1237.
    - Changed the following issues from Tentatively Ready to WP: 556, 676, 704, 724, 727, 780, 811, 817, 870, 891, 893, 929, 978, 987, 999, 1033, 1034, 1071, 1089, 1108, 1110, 1113, 1114, 1126, 1130, 1131, 1133, 1137, 1138, 1152, 1158, 1170, 1177, 1180, 1182, 1189, 1192, 1193, 1195, 1197, 1199, 1205, 1208, 1209, 1218, 1220, 1221, 1222, 1231, 1241, 1245, 1247, 1250, 1254, 1255, 1256, 1257, 1261, 1262, 1264, 1267, 1270, 1271, 1276, 1277, 1280, 1284, 1285, 1286, 1287, 1288, 1298, 1299, 1303, 1306, 1309, 1312.
- R69: 2010-02-12 pre-Pittsburgh mailing.
  - Summary:
    - 266 open issues, up by 61.
    - 1052 closed issues, down by 3.
    - 1318 issues total, up by 58.
  - Details:
    - Added the following New issues: 1266, 1268, 1269, 1272, 1275, 1278, 1279, 1281, 1289, 1290, 1291, 1292, 1294, 1295, 1297, 1302, 1305, 1307, 1308, 1310, 1311, 1313, 1314, 1316, 1317, 1318.
    - Added the following Tentatively NAD issues: 1263, 1265, 1296.
    - Added the following Tentatively NAD Editorial issues: 1283, 1301.
    - Added the following Tentatively NAD Future issues: 1282.
    - Added the following Tentatively Ready issues: 1261, 1262, 1264, 1267, 1270, 1271, 1273, 1274, 1276, 1277, 1280, 1284, 1285, 1286, 1287, 1288, 1293, 1298, 1299, 1300, 1303, 1304, 1306, 1309, 1312, 1315.
    - Changed the following issues from NAD to NAD Editorial: 101.
    - Changed the following issues from NAD Future to Open: 1248.
    - Changed the following issues from New to Open: 1207.
    - Changed the following issues from Ready to Open: 1079.
    - Changed the following issues from New to Tentatively Dup: 1219.
    - Changed the following issues from New to Tentatively NAD: 1125, 1176, 1202, 1223, 1224, 1246, 1251, 1259.
    - Changed the following issues from Open to Tentatively NAD: 726, 959.
    - Changed the following issues from Review to Tentatively NAD: 631.
    - Changed the following issues from Open to Tentatively NAD Concepts: 910.
    - Changed the following issues from New to Tentatively NAD Editorial: 1258.
    - Changed the following issues from Open to Tentatively NAD Editorial: 815, 1106.
    - Changed the following issues from Ready to Tentatively NAD Editorial: 816, 889.
    - Changed the following issues from NAD to Tentatively Ready: 579.
    - Changed the following issues from NAD Editorial to Tentatively Ready: 1195.
    - Changed the following issues from New to Tentatively Ready: 1131, 1133, 1137, 1170, 1180, 1182, 1193, 1197, 1199, 1205, 1209, 1218, 1221, 1222, 1245, 1250, 1254, 1255, 1256, 1257.
    - Changed the following issues from Open to Tentatively Ready: 704, 724, 811, 817, 870, 891, 1033, 1034, 1089, 1110.
    - Changed the following issues from Ready to Tentatively Ready: 893, 978, 1177.
    - Changed the following issues from Review to Tentatively Ready: 556, 676, 727, 780, 929, 1130, 1247.
    - Changed the following issues from Pending WP to WP: 970.
- R68: 2009-11-06 post-Santa Cruz mailing.
  - Summary:
    - 205 open issues, down by 77.
    - 1055 closed issues, up by 120.
    - 1260 issues total, up by 43.
  - Details:
    - Added the following Dup issues: 1230.
    - Added the following NAD issues: 1229, 1236, 1243.
    - Added the following NAD Editorial issues: 1232.
    - Added the following NAD Future issues: 1235, 1242, 1248.
    - Added the following New issues: 1218, 1219, 1221, 1222, 1223, 1224, 1225, 1234, 1240, 1244, 1245, 1246, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260.
    - Added the following Open issues: 1228.
    - Added the following Ready issues: 1227, 1237.
    - Added the following Review issues: 1247.
    - Added the following Tentatively NAD Editorial issues: 1233, 1239.
    - Added the following Tentatively NAD Future issues: 1238.
    - Added the following Tentatively Ready issues: 1220, 1226, 1231, 1241.
    - Changed the following issues from New to NAD: 1132, 1148.
    - Changed the following issues from Open to NAD: 96, 458, 463, 916, 917, 919, 955, 977, 1009, 1020, 1035, 1042, 1051, 1064.
    - Changed the following issues from Review to NAD: 668, 930, 1091, 1102.
    - Changed the following issues from Tentatively NAD to NAD: 588, 617, 971.
    - Changed the following issues from Tentatively NAD Future to NAD: 1062.
    - Changed the following issues from NAD Concepts to NAD Editorial: 1143.
    - Changed the following issues from New to NAD Editorial: 1116, 1117, 1122, 1129, 1145, 1146, 1147, 1155, 1166, 1172, 1174, 1179, 1195, 1196.
    - Changed the following issues from Open to NAD Editorial: 431, 580, 635, 719, 823, 827, 879, 880, 908, 923, 924, 926, 944, 947, 958, 1046, 1048, 1054, 1055, 1075, 1088, 1160, 1161, 1162, 1163, 1165.
    - Changed the following issues from Review to NAD Editorial: 828, 897, 976, 1043, 1047, 1049, 1050.
    - Changed the following issues from New to NAD Future: 1120, 1150, 1184, 1203, 1217.
    - Changed the following issues from Open to NAD Future: 484, 532, 851, 933, 935, 936, 961, 1041, 1053.
    - Changed the following issues from Tentatively NAD Future to NAD Future: 1031.
    - Changed the following issues from New to Open: 1118, 1119, 1151, 1153, 1156, 1171, 1173, 1183, 1191, 1211.
    - Changed the following issues from Ready to Open: 430, 834.
    - Changed the following issues from Review to Open: 397, 408, 835.
    - Changed the following issues from Tentatively NAD to Open: 625.
    - Changed the following issues from New to Ready: 1123, 1134, 1135, 1136, 1144, 1177, 1194, 1204, 1216.
    - Changed the following issues from Open to Ready: 296, 471, 485, 539, 816, 860, 865, 872, 920, 932, 939, 940, 960, 963, 974, 978, 1011, 1030, 1079, 1098.
    - Changed the following issues from Review to Ready: 473, 671, 836, 854, 868, 871, 889, 893, 921, 950, 954, 957, 962, 967, 968, 983, 1052, 1094, 1095, 1097, 1100, 1104, 1157.
    - Changed the following issues from New to Review: 1130.
    - Changed the following issues from Open to Review: 556, 631, 676, 727, 929.
    - Changed the following issues from Open to Tentatively NAD: 1056, 1099.
    - Changed the following issues from New to Tentatively NAD Concepts: 1186.
    - Changed the following issues from New to Tentatively NAD Editorial: 1115.
    - Changed the following issues from New to Tentatively NAD Future: 1121, 1201.
    - Changed the following issues from Open to Tentatively NAD Future: 1112.
    - Changed the following issues from New to Tentatively Ready: 1126, 1138, 1152, 1158, 1189, 1192, 1208.
    - Changed the following issues from Open to Tentatively Ready: 987, 999, 1071, 1090, 1108, 1113, 1114.
    - Changed the following issues from Ready to WP: 149, 419, 498, 564, 565, 630, 659, 696, 711, 716, 723, 788, 822, 838, 847, 857, 859, 876, 881, 883, 886, 934, 1004, 1178.
    - Changed the following issues from Tentatively Ready to WP: 1012, 1019.
- R67: 2009-09-25 pre-Santa Cruz mailing.
  - Summary:
    - 282 open issues, up by 32.
    - 935 closed issues, down by 1.
    - 1217 issues total, up by 31.
  - Details:
    - Added the following New issues: 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217.
    - Changed the following issues from NAD to Open: 296.
    - Changed the following issues from WP to Pending WP: 970.
    - Changed the following issues from Open to Review: 976, 1052.
    - Changed the following issues from Ready to Review: 780.
- R66: 2009-07-31 post-Frankfurt mailing.
  - Summary:
    - 250 open issues, down by 128.
    - 936 closed issues, up by 171.
    - 1186 issues total, up by 43.
  - Details:
    - Added the following NAD issues: 1164.
    - Added the following NAD Concepts issues: 1149, 1167.
    - Added the following NAD Editorial issues: 1168.
    - Added the following New issues: 1144, 1145, 1146, 1147, 1148, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1158, 1159, 1166, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186.
    - Added the following Open issues: 1160, 1161, 1162, 1163, 1165.
    - Added the following Ready issues: 1178.
    - Added the following Review issues: 1157.
    - Changed the following issues from Open to Dup: 750, 895.
    - Changed the following issues from Open to NAD: 111, 128, 138, 190, 219, 290, 309, 342, 343, 382, 394, 398, 417, 418, 421, 459, 466, 492, 502, 503, 546, 573, 582, 585, 597, 606, 614, 632, 721, 747, 751, 833, 941, 992.
    - Changed the following issues from Review to NAD: 1003.
    - Changed the following issues from Tentatively NAD to NAD: 568, 644, 667, 669, 701, 702, 785, 863, 901, 903, 946, 988, 995.
    - Changed the following issues from Tentatively Ready to NAD: 1002.
    - Changed the following issues from New to NAD Concepts: 1124, 1127, 1128, 1139, 1140, 1141, 1142, 1143.
    - Changed the following issues from Open to NAD Concepts: 902, 989, 1000, 1007, 1010, 1015, 1016, 1017, 1018, 1026, 1027, 1028, 1029, 1032, 1036, 1057, 1059, 1072, 1078, 1081, 1082, 1083, 1084, 1085, 1086, 1092, 1096, 1105.
    - Changed the following issues from Review to NAD Concepts: 1001, 1005, 1080, 1087, 1111.
    - Changed the following issues from Tentatively NAD to NAD Concepts: 912, 918, 1074.
    - Changed the following issues from Tentatively NAD Editorial to NAD Concepts: 927, 1109.
    - Changed the following issues from Tentatively Ready to NAD Concepts: 906, 913, 914, 928, 1024, 1063, 1067.
    - Changed the following issues from Open to NAD Editorial: 718, 873.
    - Changed the following issues from Tentatively NAD Editorial to NAD Editorial: 424, 825, 830, 837, 862, 867, 884, 945, 952, 969, 972, 973, 979, 1023, 1058, 1060, 1061, 1077, 1101.
    - Changed the following issues from Tentatively Ready to NAD Editorial: 1013, 1107.
    - Changed the following issues from Open to NAD Future: 255, 423, 523, 708, 760, 839, 877.
    - Changed the following issues from CD1 to Open: 823.
    - Changed the following issues from NAD Editorial to Open: 299, 484, 532, 556, 594, 631, 676, 704, 724, 742, 811, 870, 872.
    - Changed the following issues from Review to Open: 879, 919, 929, 939, 987, 1009, 1093.
    - Changed the following issues from Tentatively NAD to Open: 458.
    - Changed the following issues from Tentatively NAD Future to Open: 96.
    - Changed the following issues from Tentatively Ready to Open: 910, 915, 932, 940, 974, 976, 999, 1011.
    - Changed the following issues from Open to Ready: 149, 419, 430, 498, 564, 565, 630, 659, 696, 711, 716, 723, 788, 834, 838, 847, 857, 859, 876, 881, 883, 886, 1004.
    - Changed the following issues from Review to Ready: 780.
    - Changed the following issues from Tentatively NAD to Ready: 822.
    - Changed the following issues from Tentatively Ready to Ready: 934.
    - Changed the following issues from NAD to Review: 871.
    - Changed the following issues from Open to Review: 397, 408, 473, 671, 836, 868, 889, 893, 930, 954, 962, 967, 968.
    - Changed the following issues from Tentatively NAD to Review: 668.
    - Changed the following issues from Tentatively Ready to Review: 950, 1100.
    - Changed the following issues from Open to Tentatively NAD: 588, 617, 625, 971.
    - Changed the following issues from Open to Tentatively NAD Future: 1031, 1062.
    - Changed the following issues from Open to Tentatively Ready: 1012, 1019.
    - Changed the following issues from Tentatively Ready to WP: 688, 765, 810, 814, 853, 869, 878, 888, 890, 898, 899, 904, 907, 909, 922, 925, 931, 938, 943, 948, 949, 965, 970, 975, 981, 982, 984, 986, 990, 991, 993, 994, 997, 998, 1006, 1014, 1021, 1037, 1038, 1039, 1040, 1044, 1045, 1065, 1066, 1070, 1073, 1103.
- R65: 2009-06-19 pre-Frankfurt mailing.
  - Summary:
    - 378 open issues, up by 32.
    - 765 closed issues, up by 0.
    - 1143 issues total, up by 32.
  - Details:
    - Added the following New issues: 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143.
    - Added the following Open issues: 1112, 1113, 1114.
    - Changed the following issues from Pending NAD Editorial to NAD Editorial: 937.
    - Changed the following issues from New to Open: 696, 716, 727, 865, 900, 911, 916, 917, 920, 933, 935, 941, 947, 951, 953, 954, 955, 956, 977, 978, 985, 989, 996, 1033, 1054, 1056, 1057, 1059, 1062, 1068, 1069, 1071, 1072, 1076, 1090, 1092, 1096, 1098, 1099, 1105, 1106, 1108, 1110.
    - Changed the following issues from Review to Open: 817, 971, 992, 1004, 1010, 1012, 1015, 1019.
    - Changed the following issues from New to Review: 780, 835, 897, 919, 939, 957, 983, 1001, 1080, 1091, 1093, 1094, 1095, 1097, 1102, 1104, 1111.
    - Changed the following issues from Open to Review: 921, 987, 1087.
    - Changed the following issues from New to Tentatively NAD: 568, 701, 702, 785, 863, 903, 912, 918, 946, 995, 1074.
    - Changed the following issues from Open to Tentatively NAD: 458, 644, 667, 668, 669.
    - Changed the following issues from Review to Tentatively NAD: 901.
    - Changed the following issues from Tentatively Ready to Tentatively NAD: 822, 988.
    - Changed the following issues from New to Tentatively NAD Editorial: 837, 862, 867, 927, 945, 952, 969, 972, 973, 979, 1058, 1060, 1061, 1077, 1101, 1109.
    - Changed the following issues from Open to Tentatively NAD Editorial: 424, 825, 830, 884.
    - Changed the following issues from Review to Tentatively NAD Editorial: 1023.
    - Changed the following issues from Open to Tentatively NAD Future: 96.
    - Changed the following issues from New to Tentatively Ready: 810, 898, 906, 910, 913, 914, 915, 925, 974, 976, 981, 982, 984, 990, 998, 999, 1063, 1067, 1070, 1073, 1100, 1103, 1107.
    - Changed the following issues from Open to Tentatively Ready: 688, 814.
    - Changed the following issues from Review to Tentatively Ready: 899, 907, 909, 934, 938, 940, 943, 950, 965, 970, 975, 986, 991, 993, 994, 997, 1002, 1006, 1011, 1013, 1014, 1021, 1024, 1037, 1038, 1039, 1040, 1044, 1045, 1065, 1066.
- R64: 2009-05-01 mid-term mailing.
  - Summary:
    - 346 open issues, up by 19.
    - 765 closed issues, up by 0.
    - 1111 issues total, up by 19.
  - Details:
    - Added the following New issues: 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111.
    - Changed the following issues from DR to CD1: 130, 386, 406, 409, 413, 434, 438, 444, 445, 455, 457, 460, 469, 533.
    - Changed the following issues from Review to New: 1070.
- R63: 2009-03-20 post-Summit mailing.
  - Summary:
    - 327 open issues, up by 96.
    - 765 closed issues, up by 14.
    - 1092 issues total, up by 110.
  - Details:
    - Added the following NAD Editorial issues: 1022.
    - Added the following NAD Future issues: 1025.
    - Added the following New issues: 983, 984, 985, 989, 990, 995, 996, 998, 999, 1001, 1033, 1054, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1067, 1068, 1069, 1071, 1072, 1073, 1074, 1076, 1077, 1080, 1090, 1091, 1092.
    - Added the following Open issues: 987, 1000, 1007, 1008, 1016, 1017, 1018, 1020, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1034, 1035, 1036, 1041, 1042, 1046, 1048, 1051, 1052, 1053, 1055, 1064, 1075, 1078, 1079, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089.
    - Added the following Review issues: 986, 991, 992, 993, 994, 997, 1002, 1003, 1004, 1005, 1006, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1019, 1021, 1023, 1024, 1037, 1038, 1039, 1040, 1043, 1044, 1045, 1047, 1049, 1050, 1065, 1066, 1070.
    - Added the following Tentatively Ready issues: 988.
    - Changed the following issues from New to Dup: 905, 942.
    - Changed the following issues from New to NAD: 980.
    - Changed the following issues from New to NAD Editorial: 874, 875.
    - Changed the following issues from Open to NAD Editorial: 732, 793, 794, 800.
    - Changed the following issues from Pending NAD Editorial to NAD Editorial: 683, 892.
    - Changed the following issues from Ready to NAD Editorial: 803.
    - Changed the following issues from NAD to Open: 466.
    - Changed the following issues from NAD Future to Open: 111, 138, 149, 219.
    - Changed the following issues from New to Open: 880, 891, 893, 902, 908, 921, 923, 924, 926, 930, 936, 944, 958, 959, 960, 961, 962, 963, 964, 966, 967, 968.
    - Changed the following issues from Ready to Open: 788.
    - Changed the following issues from New to Pending NAD Editorial: 937.
    - Changed the following issues from New to Review: 879, 899, 901, 907, 909, 929, 934, 938, 940, 943, 950, 965, 970, 971, 975.
    - Changed the following issues from Open to Review: 817.
    - Changed the following issues from New to Tentatively Ready: 904, 922, 928, 931, 932, 948, 949.
    - Changed the following issues from Open to Tentatively Ready: 890.
    - Changed the following issues from Review to Tentatively Ready: 765, 822, 853, 869, 878, 888.
    - Changed the following issues from Ready to WP: 752, 753, 758, 821, 866, 894.
- R62: 2009-02-06 pre-Summit mailing.
  - Summary:
    - 231 open issues, up by 44.
    - 751 closed issues, up by 0.
    - 982 issues total, up by 44.
  - Details:
    - Added the following New issues: 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982.
- R61: 2008-12-05 mid-term mailing.
  - Summary:
    - 187 open issues, up by 20.
    - 751 closed issues, up by 0.
    - 938 issues total, up by 20.
  - Details:
    - Added the following New issues: 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938.
- R60: 2008-10-03 post-San Francisco mailing.
  - Summary:
    - 167 open issues, down by 25.
    - 751 closed issues, up by 65.
    - 918 issues total, up by 40.
  - Details:
    - Added the following CD1 issues: 882.
    - Added the following New issues: 879, 880, 891, 893, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918.
    - Added the following Open issues: 881, 883, 884, 885, 886, 887, 889, 890, 895, 896.
    - Added the following Pending NAD Editorial issues: 892.
    - Added the following Ready issues: 894.
    - Added the following Review issues: 888.
    - Changed the following issues from New to CD1: 818, 820, 843, 845, 846, 856, 858.
    - Changed the following issues from Ready to CD1: 180, 387, 396, 522, 629, 691, 713, 714, 720, 728, 762, 769, 771, 772, 776, 779, 787, 805, 806, 807, 808, 809, 813, 824, 829, 842, 844, 848, 850, 852.
    - Changed the following issues from Review to CD1: 23, 675, 692, 698, 709, 734, 804, 823.
    - Changed the following issues from WP to CD1: 44, 49, 76, 91, 92, 98, 103, 109, 117, 118, 120, 123, 136, 153, 165, 167, 171, 179, 182, 183, 184, 185, 186, 187, 198, 200, 201, 202, 206, 214, 221, 225, 226, 228, 229, 230, 231, 232, 233, 234, 235, 237, 238, 239, 240, 241, 242, 243, 247, 248, 250, 251, 252, 253, 254, 256, 258, 259, 260, 261, 262, 263, 264, 265, 266, 268, 270, 271, 272, 273, 274, 275, 276, 278, 280, 281, 282, 283, 284, 285, 286, 288, 291, 292, 294, 295, 297, 298, 300, 301, 303, 305, 306, 307, 308, 310, 311, 312, 315, 316, 317, 318, 319, 320, 321, 322, 324, 325, 327, 328, 329, 331, 333, 334, 335, 336, 337, 338, 339, 340, 341, 345, 346, 347, 349, 352, 354, 355, 358, 359, 360, 362, 363, 364, 365, 369, 370, 371, 373, 375, 376, 379, 380, 381, 383, 384, 389, 391, 395, 400, 401, 402, 403, 404, 405, 407, 410, 411, 412, 414, 415, 416, 420, 422, 425, 426, 428, 432, 435, 436, 441, 442, 443, 448, 449, 453, 456, 461, 464, 465, 467, 468, 474, 475, 478, 488, 495, 496, 497, 505, 507, 508, 518, 519, 520, 521, 524, 527, 530, 531, 534, 535, 537, 538, 540, 541, 542, 543, 545, 550, 551, 552, 559, 561, 562, 563, 566, 567, 574, 575, 576, 577, 578, 581, 586, 589, 593, 595, 596, 607, 608, 609, 610, 611, 612, 613, 616, 618, 619, 620, 621, 622, 623, 624, 628, 634, 638, 640, 643, 646, 650, 651, 652, 654, 655, 660, 661, 664, 665, 666, 672, 673, 674, 677, 678, 679, 680, 681, 682, 685, 687, 689, 693, 694, 695, 699, 700, 703, 705, 706, 710, 712, 715, 722, 740, 743, 744, 746, 749, 755, 759, 761, 766, 768, 770, 775, 777, 778, 781, 782, 783, 789, 792, 798.
    - Changed the following issues from Open to Dup: 670.
    - Changed the following issues from New to NAD: 849, 855, 871.
    - Changed the following issues from Open to NAD: 454, 832.
    - Changed the following issues from New to NAD Editorial: 811, 812, 841, 864, 870, 872.
    - Changed the following issues from Open to NAD Editorial: 299, 484, 556, 631, 676, 704, 724, 742.
    - Changed the following issues from Pending NAD Editorial to NAD Editorial: 532, 594, 717, 725, 738.
    - Changed the following issues from New to Open: 721, 751, 814, 816, 817, 819, 827, 836, 838, 847, 857, 859, 860, 861, 868, 873, 876, 877.
    - Changed the following issues from Pending NAD Editorial to Open: 424, 625.
    - Changed the following issues from Review to Open: 851.
    - Changed the following issues from New to Ready: 788, 821, 866.
    - Changed the following issues from Open to Ready: 753.
    - Changed the following issues from Review to Ready: 752, 758, 803.
    - Changed the following issues from New to Review: 765, 822, 853, 854, 869, 878.
    - Changed the following issues from TC to TC1: 1, 3, 5, 7, 8, 9, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 46, 47, 48, 50, 51, 52, 53, 54, 55, 56, 57, 59, 60, 61, 62, 63, 64, 66, 68, 69, 70, 71, 74, 75, 78, 79, 80, 83, 86, 90, 106, 108, 110, 112, 114, 115, 119, 122, 124, 125, 126, 127, 129, 132, 133, 134, 137, 139, 141, 142, 144, 146, 147, 148, 150, 151, 152, 154, 155, 156, 158, 159, 160, 161, 164, 168, 169, 170, 172, 173, 174, 175, 176, 181, 189, 193, 195, 199, 208, 209, 210, 211, 212, 217, 220, 222, 223, 224, 227.
- R59: 2008-08-22 pre-San Francisco mailing.
  - Summary:
    - 192 open issues, up by 9.
    - 686 closed issues, up by 0.
    - 878 issues total, up by 9.
  - Details:
    - Added the following New issues: 870, 871, 872, 873, 874, 875, 876, 877, 878.
- R58: 2008-07-28 mid-term mailing.
  - Summary:
    - 183 open issues, up by 12.
    - 686 closed issues, down by 4.
    - 869 issues total, up by 8.
  - Details:
    - Added the following New issues: 862, 863, 864, 865, 866, 867, 868, 869.
    - Changed the following issues from Pending NAD Editorial to NAD Editorial: 393, 557, 592, 754, 757.
    - Changed the following issues from Pending WP to Open: 644.
    - Changed the following issues from WP to Ready: 387, 629.
    - Changed the following issues from Pending NAD Editorial to Review: 709.
- R57: 2008-06-27 post-Sophia Antipolis mailing.
  - Summary:
    - 171 open issues, down by 20.
    - 690 closed issues, up by 43.
    - 861 issues total, up by 23.
  - Details:
    - Added the following NAD issues: 840.
    - Added the following New issues: 841, 843, 845, 846, 847, 849, 853, 854, 855, 856, 857, 858, 859, 860, 861.
    - Added the following Open issues: 839.
    - Added the following Ready issues: 842, 844, 848, 850, 852.
    - Added the following Review issues: 851.
    - Changed the following issues from New to NAD: 826.
    - Changed the following issues from Open to NAD: 570.
    - Changed the following issues from New to NAD Editorial: 786, 831.
    - Changed the following issues from Open to NAD Editorial: 756, 767.
    - Changed the following issues from New to Open: 723, 726, 794, 815, 825, 830, 833, 834.
    - Changed the following issues from Ready to Open: 471.
    - Changed the following issues from Review to Open: 539, 711.
    - Changed the following issues from New to Ready: 713, 714, 769, 772, 779, 787, 805, 806, 807, 808, 809, 813, 824, 829.
    - Changed the following issues from Open to Ready: 180, 396, 522, 720, 762.
    - Changed the following issues from Review to Ready: 691, 728, 771, 776.
    - Changed the following issues from New to Review: 692, 698, 752, 804, 823, 828, 832.
    - Changed the following issues from Open to Review: 23, 675, 734, 803.
    - Changed the following issues from Ready to Review: 758.
    - Changed the following issues from Ready to WP: 387, 518, 550, 574, 595, 596, 612, 618, 629, 638, 672, 673, 685, 710, 715, 722, 740, 743, 744, 746, 749, 755, 759, 761, 766, 768, 770, 775, 777, 778, 781, 782, 783, 789, 792, 798.
- R56: 2008-05-16 pre-Sophia Antipolis mailing.
  - Summary:
    - 191 open issues, up by 24.
    - 647 closed issues, up by 1.
    - 838 issues total, up by 25.
  - Details:
    - Added the following New issues: 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838.
    - Changed the following issues from New to NAD: 802.
- R55: 2008-03-14 post-Bellevue mailing.
  - Summary:
    - 167 open issues, down by 39.
    - 646 closed issues, up by 65.
    - 813 issues total, up by 26.
  - Details:
    - Added the following Dup issues: 795.
    - Added the following NAD issues: 790, 791, 796, 797, 799.
    - Added the following New issues: 788, 794, 802, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813.
    - Added the following Open issues: 793, 800, 801, 803.
    - Added the following Ready issues: 789, 792, 798.
    - Changed the following issues from NAD Future to Dup: 116.
    - Changed the following issues from NAD Future to NAD: 188, 323.
    - Changed the following issues from New to NAD: 729, 730, 731, 733, 735, 736, 737, 739, 741, 745, 748, 763, 764, 773, 784.
    - Changed the following issues from Open to NAD: 388, 462, 579, 627, 653, 686, 707.
    - Changed the following issues from NAD Future to NAD Editorial: 140, 390.
    - Changed the following issues from Open to NAD Editorial: 529, 626.
    - Changed the following issues from Review to NAD Editorial: 645, 684.
    - Changed the following issues from NAD Future to Open: 128, 180, 190.
    - Changed the following issues from New to Open: 617, 718, 719, 720, 724, 732, 734, 742, 747, 750, 753, 756, 760, 762, 767, 774.
    - Changed the following issues from Ready to Open: 675, 676, 688.
    - Changed the following issues from New to Pending NAD Editorial: 709, 717, 725, 738, 754, 757.
    - Changed the following issues from Open to Pending NAD Editorial: 424, 557, 625.
    - Changed the following issues from New to Ready: 710, 715, 722, 740, 743, 744, 746, 749, 755, 758, 759, 761, 766, 768, 770, 775, 777, 778, 781, 782, 783.
    - Changed the following issues from Open to Ready: 387, 471, 550, 612, 629, 673.
    - Changed the following issues from Review to Ready: 518, 574, 596, 618, 638, 672, 685.
    - Changed the following issues from New to Review: 711, 728, 771, 776.
    - Changed the following issues from Open to Review: 539.
    - Changed the following issues from Ready to WP: 561, 562, 563, 567, 581, 620, 621, 622, 623, 624, 661, 664, 665, 666, 674, 679, 680, 687, 689, 693, 694, 695, 700, 703, 705, 706.
    - Changed the following issues from Tentatively Ready to WP: 527.
- R54: 2008-02-01 pre-Bellevue mailing.
  - Summary:
    - 206 open issues, up by 23.
    - 581 closed issues, up by 0.
    - 787 issues total, up by 23.
  - Details:
    - Added the following New issues: 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787.
    - Changed the following issues from NAD Future to Dup: 105, 348.
    - Changed the following issues from NAD Future to NAD Editorial: 353.
    - Changed the following issues from New to NAD Editorial: 697.
    - Changed the following issues from NAD Future to Open: 388.
    - Changed the following issues from Open to Tentatively Ready: 527.
- R53: 2007-12-09 mid-term mailing.
  - Summary:
    - 183 open issues, up by 11.
    - 581 closed issues, down by 1.
    - 764 issues total, up by 10.
  - Details:
    - Added the following New issues: 755, 756, 757, 758, 759, 760, 761, 762, 763, 764.
    - Changed the following issues from NAD to Open: 463.
    - Changed the following issues from Pending WP to WP: 607, 608, 654, 655, 677, 682.
- R52: 2007-10-19 post-Kona mailing.
  - Summary:
    - 172 open issues, up by 4.
    - 582 closed issues, up by 27.
    - 754 issues total, up by 31.
  - Details:
    - Added the following New issues: 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754.
    - Changed the following issues from NAD Future to Dup: 77, 350.
    - Changed the following issues from New to NAD: 639, 657, 663.
    - Changed the following issues from Open to NAD: 548.
    - Changed the following issues from New to Open: 546, 550, 564, 565, 573, 585, 588, 627, 629, 630, 632, 635, 653, 659, 667, 668, 669, 670, 671, 673, 686, 704, 707, 708.
    - Changed the following issues from New to Pending NAD Editorial: 393, 592.
    - Changed the following issues from New to Pending WP: 607, 608, 654, 655, 677, 682.
    - Changed the following issues from New to Ready: 561, 562, 563, 567, 581, 595, 620, 621, 622, 623, 624, 661, 664, 665, 666, 674, 675, 676, 679, 687, 688, 689, 693, 694, 695, 700, 703, 705, 706.
    - Changed the following issues from Open to Ready: 680.
    - Changed the following issues from New to Review: 574, 596, 618, 638, 645, 672, 684, 685, 691.
    - Changed the following issues from New to WP: 552, 634, 650, 651, 652, 678, 681, 699, 712.
    - Changed the following issues from Open to WP: 258, 401, 524.
    - Changed the following issues from Ready to WP: 488, 577, 660.
- R51: 2007-09-09 pre-Kona mailing.
  - Summary:
    - 168 open issues, up by 15.
    - 555 closed issues, up by 0.
    - 723 issues total, up by 15.
  - Details:
    - Added the following New issues: 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723.
- R50: 2007-08-05 post-Toronto mailing.
  - Summary:
    - 153 open issues, down by 5.
    - 555 closed issues, up by 17.
    - 708 issues total, up by 12.
  - Details:
    - Added the following New issues: 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708.
    - Changed the following issues from New to NAD: 583, 584, 662.
    - Changed the following issues from Open to NAD: 528.
    - Changed the following issues from New to NAD Editorial: 637, 647, 658, 690.
    - Changed the following issues from Open to NAD Editorial: 525.
    - Changed the following issues from Pending NAD Editorial to NAD Editorial: 553, 571, 591, 633, 636, 641, 642, 648, 649, 656.
    - Changed the following issues from New to Open: 579, 631, 680.
    - Changed the following issues from Pending WP to Open: 258.
    - Changed the following issues from Ready to Pending WP: 644.
    - Changed the following issues from New to Ready: 577, 660.
    - Changed the following issues from Open to Ready: 488.
    - Changed the following issues from Open to Review: 518.
    - Changed the following issues from Ready to TRDec: 604.
    - Changed the following issues from DR to WP: 453.
    - Changed the following issues from Ready to WP: 531, 551, 566, 628, 640, 643, 646.
- R49: 2007-06-23 pre-Toronto mailing.
  - Summary:
    - 158 open issues, up by 13.
    - 538 closed issues, up by 7.
    - 696 issues total, up by 20.
  - Details:
    - Added the following New issues: 677, 678, 679, 680, 681, 682, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696.
    - Added the following Pending NAD Editorial issues: 683.
    - Changed the following issues from New to NAD Editorial: 587.
    - Changed the following issues from Open to NAD Editorial: 590.
    - Changed the following issues from New to Pending NAD Editorial: 636, 642, 648, 649.
- R48: 2007-05-06 post-Oxford mailing.
  - Summary:
    - 145 open issues, down by 33.
    - 531 closed issues, up by 53.
    - 676 issues total, up by 20.
  - Details:
    - Added the following New issues: 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676.
    - Changed the following issues from Tentatively Ready to Dup: 479, 536.
    - Changed the following issues from Tentatively Ready to NAD: 385, 463, 466, 470, 515, 526, 547, 560, 572.
    - Changed the following issues from NAD to NAD Editorial: 351, 357, 368, 499, 504, 512, 513, 514, 516, 544, 549, 555, 558.
    - Changed the following issues from Tentatively Ready to NAD Editorial: 482, 615.
    - Changed the following issues from NAD_Future to NAD Future: 77, 105, 111, 116, 128, 138, 140, 149, 180, 188, 190, 219, 323, 348, 350, 353, 388, 390.
    - Changed the following issues from Tentatively Ready to Open: 471.
    - Changed the following issues from New to Pending NAD Editorial: 633, 641, 656.
    - Changed the following issues from Tentatively Ready to Pending NAD Editorial: 532, 553, 571, 591, 594.
    - Changed the following issues from Tentatively Ready to Pending WP: 258.
    - Changed the following issues from New to Ready: 566, 628, 640, 643, 644, 646.
    - Changed the following issues from Review to Ready: 531, 551, 604.
    - Changed the following issues from Ready to TRDec: 598, 599, 600, 601, 602, 603, 605.
    - Changed the following issues from Ready to WP: 543, 545.
    - Changed the following issues from Tentatively Ready to WP: 201, 206, 233, 254, 416, 422, 456, 534, 542, 559, 575, 576, 578, 586, 589, 593, 609, 610, 611, 613, 616, 619.
- R47: 2007-03-09 pre-Oxford mailing.
  - Summary:
    - 178 open issues, up by 37.
    - 478 closed issues, up by 0.
    - 656 issues total, up by 37.
  - Details:
    - Added the following New issues: 620, 621, 622, 623, 624, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656.
    - Added the following Open issues: 625, 626.
    - Changed the following issues from New to Open: 570, 580, 582, 590, 612, 614.
    - Changed the following issues from New to Tentatively Ready: 547, 553, 560, 571, 572, 575, 576, 578, 586, 589, 591, 593, 594, 609, 610, 611, 613, 615, 616, 619.
    - Changed the following issues from Open to Tentatively Ready: 201, 206, 233, 254, 258, 385, 416, 422, 456, 463, 466, 470, 471, 479, 482, 515, 526, 532, 536, 542, 559.
    - Changed the following issues from Review to Tentatively Ready: 534.
- R46: 2007-01-12 mid-term mailing.
  - Summary:
    - 141 open issues, up by 11.
    - 478 closed issues, down by 1.
    - 619 issues total, up by 10.
  - Details:
    - Added new issues 610, 611, 612, 613, 614, 615, 616, 617, 618, 619.
- R45: 2006-11-03 post-Portland mailing.
  - Summary:
    - 130 open issues, up by 0.
    - 479 closed issues, up by 17.
    - 609 issues total, up by 17.
  - Details:
    - Moved issues 520, 521, 530, 535, 537, 538, 540, 541 to WP.
    - Moved issues 504, 512, 516, 544, 549, 554, 555, 558 to NAD.
    - Moved issue 569 to Dup.
    - Moved issues 518, 523, 524, 542, 556, 557, 559, 597, 606 to Open.
    - Moved issues 543, 545, 549, 549, 598 - 603, 605 to Ready.
    - Moved issues 531, 551, 604 to Review.
    - Added new issues 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609.
- R44: 2006-09-08 pre-Portland mailing.
  - Summary:
    - 130 open issues, up by 6.
    - 462 closed issues, down by 1.
    - 592 issues total, up by 5.
  - Details:
    - Added new issues 583, 584, 585, 586, 587, 588, 589, 590, 591, 592.
- R43: 2006-06-23 mid-term mailing.
  - Summary:
    - 124 open issues, up by 14.
    - 463 closed issues, down by 1.
    - 587 issues total, up by 13.
  - Details:
    - Added new issues 575, 576, 577, 578, 579, 580, 581, 582.
    - Reopened 255.
    - Moved issues 520, 541, 544, 569 to Tentatively Ready.
- R42: 2006-04-21 post-Berlin mailing.
  - Summary:
    - 110 open issues, down by 16.
    - 464 closed issues, up by 24.
    - 574 issues total, up by 8.
  - Details:
    - Added new issues 567, 568, 569, 570, 571, 572.
    - Moved issues 499, 501, 506, 509, 510, 511, 513, 514, 517 to NAD.
    - Moved issues 502, 503, 515, 516, 522, 525, 526, 527, 528, 529, 532, 536, 539, 548 to Open.
    - Moved issue 504, 512, 521, 530, 531, 535, 537, 538, 540, 549 to Ready.
    - Moved issues 247, 294, 362, 369, 371, 376, 384, 475, 478, 495, 497, 505, 507, 508, 519 to WP.
    - Moved issue 534 to Review.
- R41: 2006-02-24 pre-Berlin mailing.
  - Summary:
    - 126 open issues, up by 31.
    - 440 closed issues, up by 0.
    - 566 issues total, up by 31.
  - Details:
    - Added new issues 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550 ,551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566.
    - Moved 342 from Ready to Open.
    - Reopened 309.
- R40: 2005-12-16 mid-term mailing.
  - Summary:
    - 95 open issues.
    - 440 closed issues.
    - 535 issues total.
  - Details:
    - Added new issues 529, 530, 531, 532, 533, 534, 535.
- R39: 2005-10-14 post-Mont Tremblant mailing. Added new issues 526-528. Moved issues 280, 461, 464, 465, 467, 468, 474, 496 from Ready to WP as per the vote from Mont Tremblant. Moved issues 247, 294, 342, 362, 369, 371, 376, 384, 475, 478, 495, 497 from Review to Ready. Moved issues 498, 504, 506, 509, 510, 511, 512, 513, 514 from New to Open. Moved issues 505, 507, 508, 519 from New to Ready. Moved issue 500 from New to NAD. Moved issue 518 from New to Review.
- R38: 2005-07-03 pre-Mont Tremblant mailing. Merged open TR1 issues in 504-522. Added new issues 523-523
- R37: 2005-06 mid-term mailing. Added new issues 498-503.
- R36: 2005-04 post-Lillehammer mailing. All issues in "ready" status except for 454 were moved to "DR" status, and all issues previously in "DR" status were moved to "WP".
- R35: 2005-03 pre-Lillehammer mailing.
- R34: 2005-01 mid-term mailing. Added new issues 488-494.
- R33: 2004-11 post-Redmond mailing. Reflects actions taken in Redmond.
- R32: 2004-09 pre-Redmond mailing: reflects new proposed resolutions and new issues received after the 2004-07 mailing. Added new issues 479-481.
- R31: 2004-07 mid-term mailing: reflects new proposed resolutions and new issues received after the post-Sydney mailing. Added new issues 463-478.
- R30: Post-Sydney mailing: reflects decisions made at the Sydney meeting. Voted all "Ready" issues from R29 into the working paper. Added new issues 460-462.
- R29: Pre-Sydney mailing. Added new issues 441-457.
- R28: Post-Kona mailing: reflects decisions made at the Kona meeting. Added new issues 432-440.
- R27: Pre-Kona mailing. Added new issues 404-431.
- R26: Post-Oxford mailing: reflects decisions made at the Oxford meeting. All issues in Ready status were voted into DR status. All issues in DR status were voted into WP status.
- R25: Pre-Oxford mailing. Added new issues 390-402.
- R24: Post-Santa Cruz mailing: reflects decisions made at the Santa Cruz meeting. All Ready issues from R23 with the exception of 253, which has been given a new proposed resolution, were moved to DR status. Added new issues 383-389. (Issues 387-389 were discussed at the meeting.) Made progress on issues 225, 226, 229: 225 and 229 have been moved to Ready status, and the only remaining concerns with 226 involve wording.
- R23: Pre-Santa Cruz mailing. Added new issues 367-382. Moved issues in the TC to TC status.
- R22: Post-Curaçao mailing. Added new issues 362-366.
- R21: Pre-Curaçao mailing. Added new issues 351-361.
- R20: Post-Redmond mailing; reflects actions taken in Redmond. Added new issues 336-350, of which issues 347-350 were added since Redmond, hence not discussed at the meeting. All Ready issues were moved to DR status, with the exception of issues 284, 241, and 267. Noteworthy issues discussed at Redmond include 120 202, 226, 233, 270, 253, 254, 323.
- R19: Pre-Redmond mailing. Added new issues 323-335.
- R18: Post-Copenhagen mailing; reflects actions taken in Copenhagen. Added new issues 312-317, and discussed new issues 271-314. Changed status of issues 103 118 136 153 165 171 183 184 185 186 214 221 234 237 243 248 251 252 256 260 261 262 263 265 268 to DR. Changed status of issues 49 109 117 182 228 230 232 235 238 241 242 250 259 264 266 267 271 272 273 275 281 284 285 286 288 292 295 297 298 301 303 306 307 308 312 to Ready. Closed issues 111 277 279 287 289 293 302 313 314 as NAD.
- R17: Pre-Copenhagen mailing. Converted issues list to XML. Added proposed resolutions for issues 49, 76, 91, 235, 250, 267. Added new issues 278-311.
- R16: post-Toronto mailing; reflects actions taken in Toronto. Added new issues 265-277. Changed status of issues 3, 8, 9, 19, 26, 31, 61, 63, 86, 108, 112, 114, 115, 122, 127, 129, 134, 137, 142, 144, 146, 147, 159, 164, 170, 181, 199, 208, 209, 210, 211, 212, 217, 220, 222, 223, 224, 227 to "DR". Reopened issue 23. Reopened issue 187. Changed issues 2 and 4 to NAD. Fixed a typo in issue 17. Fixed issue 70: signature should be changed both places it appears. Fixed issue 160: previous version didn't fix the bug in enough places.
- R15: pre-Toronto mailing. Added issues 233-264. Some small HTML formatting changes so that we pass Weblint tests.
- R14: post-Tokyo II mailing; reflects committee actions taken in Tokyo. Added issues 228 to 232. (00-0019R1/N1242)
- R13: pre-Tokyo II updated: Added issues 212 to 227.
- R12: pre-Tokyo II mailing: Added issues 199 to 211. Added "and paragraph 5" to the proposed resolution of issue 29. Add further rationale to issue 178.
- R11: post-Kona mailing: Updated to reflect LWG and full committee actions in Kona (99-0048/N1224). Note changed resolution of issues 4 and 38. Added issues 196 to 198. Closed issues list split into "defects" and "closed" documents. Changed the proposed resolution of issue 4 to NAD, and changed the wording of proposed resolution of issue 38.
- R10: pre-Kona updated. Added proposed resolutions 83, 86, 91, 92, 109. Added issues 190 to 195. (99-0033/D1209, 14 Oct 99)
- R9: pre-Kona mailing. Added issues 140 to 189. Issues list split into separate "active" and "closed" documents. (99-0030/N1206, 25 Aug 99)
- R8: post-Dublin mailing. Updated to reflect LWG and full committee actions in Dublin. (99-0016/N1193, 21 Apr 99)
- R7: pre-Dublin updated: Added issues 130, 131, 132, 133, 134, 135, 136, 137, 138, 139 (31 Mar 99)
- R6: pre-Dublin mailing. Added issues 127, 128, and 129. (99-0007/N1194, 22 Feb 99)
- R5: update issues 103, 112; added issues 114 to 126. Format revisions to prepare for making list public. (30 Dec 98)
- R4: post-Santa Cruz II updated: Issues 110, 111, 112, 113 added, several issues corrected. (22 Oct 98)
- R3: post-Santa Cruz II: Issues 94 to 109 added, many issues updated to reflect LWG consensus (12 Oct 98)
- R2: pre-Santa Cruz II: Issues 73 to 93 added, issue 17 updated. (29 Sep 98)
- R1: Correction to issue 55 resolution, 60 code format, 64 title. (17 Sep 98)

## Issue Status

Issues reported to the LWG transition through a variety of statuses, indicating their progress towards a resolution. Typically, most issues will flow through the following stages.

New - The issue has not yet been reviewed by the LWG. Any Proposed Resolution is purely a suggestion from the issue submitter, and should not be construed as the view of LWG.

Open - The LWG has discussed the issue but is not yet ready to move the issue forward. There are several possible reasons for open status:

- Consensus may have not yet have been reached as to how to deal with the issue.
- Informal consensus may have been reached, but the LWG awaits exact Proposed Resolution wording for review.
- The LWG wishes to consult additional technical experts before proceeding.
- The issue may require further study.

A Proposed Resolution for an open issue is still not be construed as the view of LWG. Comments on the current state of discussions are often given at the end of open issues in an italic font. Such comments are for information only and should not be given undue importance.

Review - Exact wording of a Proposed Resolution is now available for review on an issue for which the LWG previously reached informal consensus.

Ready - The LWG has reached consensus that the issue is a defect in the Standard, the Proposed Resolution is correct, and the issue is ready to forward to the full committee for further action as a Defect Report (DR).

Typically, an issue must have a proposed resolution in the currently published issues list, whose wording does not change during LWG review, to move to the Ready status.

Voting - This status should not be seen in a published issues list, but is a marker for use during meetings to indicate an issues was Ready in the pre-meeting mailing, the Proposed Resolution is correct, and the issue will be offered to the working group at the end of the current meeting to apply to the current working paper (WP) or to close in some other appropriate manner. This easily distinguishes such issues from those moving to Ready status during the meeting itself, that should not be forwarded until the next meeting. If the issue does not move forward, it should fall back to one of the other open states before the next list is published.

Immediate - This status should not be seen in a published issues list, but is a marker for use during meetings to indicate an issues was not Ready in the pre-meeting mailing, but the Proposed Resolution is correct, and the issue will be offered to the working group at the end of the current meeting to apply to the current working paper (WP) or to close in some other appropriate manner. This status is used only rarely, typically for fixes that are both small and obvious, and usually within a meeting of the expected publication of a revised standard. If the issue does not move forward, it should fall back to one of the other open states before the next list is published.

In addition, there are a few ways to categorise and issue that remains open to a resolution within the library, but is not actively being worked on.

Deferred - The LWG has discussed the issue, is not yet ready to move the issue forward, but neither does it deem the issue significant enough to delay publishing a standard or Technical Report. A typical deferred issue would be seeking to clarify wording that might be technically correct, but easily mis-read.

A Proposed Resolution for a deferred issue is still not be construed as the view of LWG. Comments on the current state of discussions are often given at the end of open issues in an italic font. Such comments are for information only and should not be given undue importance.

Core - The LWG has discussed the issue, and feels that some key part of resolving the issue is better handled by a cleanup of the language in the Core part of the standard. The issue is passed to the Core Working Group, which should ideally open a corresponding issue that can be linked from the library issue. Such issues will be revisitted after Core have made (or declined to make) any changes.

EWG - The LWG has discussed the issue, and wonder that some key part of resolving the issue is better handled by some (hopefully small) extension to the language. The issue is passed to the Evolution Working Group, which should ideally open a corresponding issue that can be linked from the library issue. Such issues will be revisitted after Evoltion have made (or declined to make) any recommendations. Positive recommendations from EWG will often mean the issue transition to Core status while we wait for some proposed new feature to land in the working paper.

Ultimately, all issues should reach closure with one of the following statuses.

DR - (Defect Report) - The full WG21/PL22.16 committee has voted to forward the issue to the Project Editor to be processed as a Potential Defect Report. The Project Editor reviews the issue, and then forwards it to the WG21 Convenor, who returns it to the full committee for final disposition. This issues list accords the status of DR to all these Defect Reports regardless of where they are in that process.

WP - (Working Paper) - The proposed resolution has not been accepted as a Technical Corrigendum, but the full WG21/PL22.16 committee has voted to apply the Defect Report's Proposed Resolution to the working paper.

C++11 - (C++ Standard, as revised for 2011) - The full WG21/PL22.16 committee has voted to accept the Defect Report's Proposed Resolution into the published 2011 revision to the C++ standard, ISO/IEC IS 14882:2011(E).

CD1 - (Committee Draft 2008) - The full WG21/PL22.16 committee has voted to accept the Defect Report's Proposed Resolution into the Fall 2008 Committee Draft.

TC1 - (Technical Corrigenda 1) - The full WG21/PL22.16 committee has voted to accept the Defect Report's Proposed Resolution as a Technical Corrigenda. Action on this issue is thus complete and no further action is possible under ISO rules.

TRDec - (Decimal TR defect) - The LWG has voted to accept the Defect Report's Proposed Resolution into the Decimal TR. Action on this issue is thus complete and no further action is expected.

Resolved - The LWG has reached consensus that the issue is a defect in the Standard, but the resolution adopted to resolve the issue came via some other mechanism than this issue in the list - typically by applying a formal paper, occasionally as a side effect of consolidating several interacting issue resolutions into a single issue.

Dup - The LWG has reached consensus that the issue is a duplicate of another issue, and will not be further dealt with. A Rationale identifies the duplicated issue's issue number.

NAD - The LWG has reached consensus that the issue is not a defect in the Standard.

NAD Editorial - The LWG has reached consensus that the issue can either be handled editorially, or is handled by a paper (usually linked to in the rationale).

NAD Future - In addition to the regular status, the LWG believes that this issue should be revisited at the next revision of the standard.

NAD Concepts - This status reflects an evolution of the language during the development of C++11, where a new feature entered the language, called concepts, that fundamentally changed the way templates would be specified and written. While this language feature was removed towards the end of the C++11 project, there is a clear intent to revisit this part of the language design. During that development, a number of issues were opened against the updated library related to use of that feature, or requesting fixes that would require exliciit use of the concepts feature. All such issues have been closed with this status, and may be revisitted should this or a similar language feature return for a future standard.

Tentatively - This is a status qualifier. The issue has been reviewed online, or at an unofficial meeting, but not in an official meeting, and some support has been formed for the qualified status. Tentatively qualified issues may be moved to the unqualified status and forwarded to full committee (if Ready) within the same meeting. Unlike Ready issues, Tentatively Ready issues will be reviewed in subcommittee prior to forwarding to full committee. When a status is qualified with Tentatively, the issue is still considered active.

Pending - This is a status qualifier. When prepended to a status this indicates the issue has been processed by the committee, and a decision has been made to move the issue to the associated unqualified status. However for logistical reasons the indicated outcome of the issue has not yet appeared in the latest working paper.

Issues are always given the status of New when they first appear on the issues list. They may progress to Open or Review while the LWG is actively working on them. When the LWG has reached consensus on the disposition of an issue, the status will then change to Dup, NAD, or Ready as appropriate. Once the full PL22.16 committee votes to forward Ready issues to the Project Editor, they are given the status of Defect Report ( DR). These in turn may become the basis for Technical Corrigenda (TC1), or are closed without action other than a Record of Response (Resolved ). The intent of this LWG process is that only issues which are truly defects in the Standard move to the formal ISO DR status.

## Active Issues

### 1169. `num_get` not fully compatible with `strto*`

Section: 22.4.2.1.2 [facet.num.get.virtuals] Status: Open Submitter: Cosmin Truta Opened: 2009-07-04 Last modified: 2014-02-11

View other active issues in [facet.num.get.virtuals].

View all other issues in [facet.num.get.virtuals].

View all issues with Open status.

Discussion:

As specified in the latest draft, N2914, `num_get` is still not fully compatible with the following C functions: `strtoul`, `strtoull`, `strtof` and `strtod`.

In C, when conversion of a string to an unsigned integer type falls outside the representable range, `strtoul` and `strtoull` return `ULONG_MAX` and `ULLONG_MAX`, respectively, regardless whether the input field represents a positive or a negative value. On the other hand, the result of `num_get` conversion of negative values to unsigned integer types is zero. This raises a compatibility issue.

Moreover, in C, when conversion of a string to a floating-point type falls outside the representable range, `strtof`, `strtod` and `strtold` return `±HUGE_VALF`, `±HUGE_VAL` and `±HUGE_VALL`, respectively. On the other hand, the result of `num_get` conversion of such out-of-range floating-point values results in the most positive/negative representable value. Although many C library implementations do implement `HUGE_VAL` (etc.) as the highest representable (which is, usually, the infinity), this isn't required by the C standard. The C library specification makes no statement regarding the value of `HUGE_VAL` and friends, which potentially raises the same compatibility issue as in the above case of unsigned integers. In addition, neither C nor C++ define symbolic constants for the maximum representable floating-point values (they only do so only for the maximum representable finite floating-point values), which raises a usability issue (it would be hard for the programmer to check the result of `num_get` against overflow).

As such, we propose to adjust the specification of `num_get` to closely follow the behavior of all of its underlying C functions.

[ 2010 Rapperswil: ]

> Some concern that this is changing the specification for an existing C++03 function, but it was pointed out that this was underspecified as resolved by issue 23. This is clean-up for that issue in turn. Some concern that we are trying to solve the same problem in both clause 22 and 27.

> Bill: There's a change here as to whether val is stored to in an error case.

> Pablo: Don't think this changes whether val is stored to or not, but changes the value that is stored.

> Bill: Remembers having skirmishes with customers and testers as to whether val is stored to, and the resolution was not to store in error cases.

> Howard: Believes since C++03 we made a change to always store in overflow.

> Everyone took some time to review the issue.

> Pablo: C++98 definitely did not store any value during an error condition.

> Dietmar: Depends on the question of what is considered an error, and whether overflow is an error or not, which was the crux of LWG 23.

> Pablo: Yes, but given the "zero, if the conversion function fails to convert the entire field", we are requiring every error condition to store.

> Bill: When did this happen?

> Alisdair: One of the last two or three meetings.

> Dietmar: To store a value in case of failure is a very bad idea.

> Move to Open, needs more study.

[2011-03-24 Madrid meeting]

Move to deferred

[ 2011 Bloomington ]

The proposed wording looks good, no-one sure why this was held back before. Move to Review.

[2012,Kona]

Move to Open.

THe issues is what to do with `-1`. Should it match 'C' or do the "sane" thing. A fix here changes behavior, but is probably what we want.

Pablo to provide wording, with help from Howard.

Proposed resolution:

Change 22.4.2.1.2 [facet.num.get.virtuals] as follows:

> Stage 3: The sequence of `char`s accumulated in stage 2 (the field) is converted to a numeric value by the rules of one of the functions declared in the header `<cstdlib>`:

> - For a signed integer value, the function `strtoll`.
> - For an unsigned integer value, the function `strtoull`.
> - For a `float` value, the function `strtof`.
> - For a `double` value, the function `strtod`.
> - For a floating-point `long double` value, the function `strtold`.

> The numeric value to be stored can be one of:

> - zero, if the conversion function fails to convert the entire field. `ios_base::failbit` is assigned to `err`.
> - the most positive (or negative) representable value, if the field to be converted to a signed integer type represents a value too large positive (or negative) to be represented in `val`. `ios_base::failbit` is assigned to `err`.
> - the most negative representable value or zero for an unsigned integer type, if the field represents a value too large negative to be represented in `val`. `ios_base::failbit` is assigned to `err`.
> - the most positive representable value, if the field to be converted to an unsigned integer type represents a value that cannot be represented in `val`.
> - the converted value, otherwise.

> The resultant numeric value is stored in `val`. If the conversion function fails to convert the entire field, or if the field represents a value outside the range of representable values, `ios_base::failbit` is assigned to `err`.

### 1175. `unordered` complexity

Section: 23.2.5 [unord.req] Status: Open Submitter: Pablo Halpern Opened: 2009-07-17 Last modified: 2014-02-11

View other active issues in [unord.req].

View all other issues in [unord.req].

View all issues with Open status.

Discussion:

When I look at the `unordered_*` constructors, I think the complexity is poorly described and does not follow the style of the rest of the standard.

The complexity for the default constructor is specified as constant. Actually, it is proportional to `n`, but there are no invocations of `value_type` constructors or other `value_type` operations.

For the iterator-based constructor the complexity should be:

> Complexity: exactly `n` calls to construct `value_type` from `InputIterator::value_type` (where `n = distance(f,l)`). The number of calls to `key_equal::operator()` is proportional to `n` in the average case and `n*n` in the worst case.

[ 2010 Rapperswil: ]

> Concern that the current wording may require O(1) where that cannot be delivered. We need to look at both the clause 23 requirements tables and the constructor description of each unordered container to be sure.

> Howard suggests NAD Editorial as we updated the container requirement tables since this issue was written.

> Daniel offers to look deeper, and hopefully produce wording addressing any outstanding concerns at the next meeting.

> Move to Open.

[2011-02-26: Daniel provides wording]

I strongly suggest to clean-up the differences between requirement tables and individual specifications. In the usual way, the most specific specifications wins, which is in this case the wrong one. In regard to the concern expressed about missing `DefaultConstructible` requirements of the value type I disagree: The function argument `n` is no size-control parameter, but only some effective capacity parameter: No elements will be value-initialized by these constructors. The necessary requirement for the value type, `EmplaceConstructible` into `*this`, is already listed in Table 103 — Unordered associative container requirements. Another part of the proposed resolution is the fact that there is an inconsistency of the complexity counting when both a range and a bucket count is involved compared to constructions where only bucket counts are provided: E.g. the construction `X a(n);` has a complexity of `n` bucket allocations, but this part of the work is omitted for `X a(i, j, n);`, even though it is considerable larger (in the average case) for `n ≫ distance(i, j)`.

[2011-03-24 Madrid meeting]

Move to deferred

[ 2011 Bloomington ]

The proposed wording looks good. Move to Review.

[2012, Kona]

Fix up some presentation issues with the wording, combining the big-O expressions into single expressions rather than the sum of two separate big-Os.

Strike "constant or linear", prefer "linear in the number of buckets". This allows for number of buckets being larger than requested `n` as well.

Default `n` to "unspecified" rather than "implementation-defined". It seems an un-necessary burden asking vendors to document a quantity that is easily determined through the public API of these classes.

Replace `distance(f,l)` with "number of elements in the range `[f,l)`"

Retain in Review with the updated wording

[2012, Portland: Move to Open]

The wording still does not call out Pablo's original concern, that the element constructor is called no more than `N` times, and that the `N` squared term applies to moves during rehash.

Inconsistent use of O(n)+O(N) vs. O(n+N), with a preference for the former.

AJM to update wording with a reference to "no more than `N` element constructor calls".

Matt concerned that calling out the O(n) requirements is noise, and dangerous noise in suggesting a precision we do not mean. The cost of constructing a bucket is very different to constructing an element of user-supplied type.

AJM notes that if there are multiple rehashes, the 'n' complexity is probably not linear.

Matt suggests back to Open, Pablo suggests potentially NAD if we keep revisitting without achieving a resolution.

Matt suggests complexity we are concerned with is the number of operations, such as constructing elements, moving nodes, and comparing/hashing keys. We are less concerned with constructing buckets, which are generally noise in this bigger picture.

Proposed resolution:

1. Modify the following rows in Table 103 — Unordered associative container requirements to add the explicit bucket allocation overhead of some constructions. As editorial recommendation it is suggested not to shorten the sum `𝒪(n) + 𝒪(N)` to `𝒪(n + N)`, because two different work units are involved.

   > Table 103 — Unordered associative container requirements (in addition to container)
   > Expression | Return type | Assertion/note pre-/post-condition | Complexity
   > --- | --- | --- | ---
   > …
   > `X(i, j, n, hf, eq)` `X a(i, j, n, hf, eq)` | `X` | … Effects: Constructs an empty container with at least `n` buckets, using `hf` as the hash function and `eq` as the key equality predicate, and inserts elements from `[i, j)` into it. | Average case 𝒪(`n + N`) (`N` is `distance(i, j)`), worst case 𝒪(`n`) + 𝒪(`N2`)
   > `X(i, j, n, hf)` `X a(i, j, n, hf)` | `X` | … Effects: Constructs an empty container with at least `n` buckets, using `hf` as the hash function and `key_equal()` as the key equality predicate, and inserts elements from `[i, j)` into it. | Average case 𝒪(`n + N`) (`N` is `distance(i, j)`), worst case 𝒪(`n + N2`)
   > `X(i, j, n)` `X a(i, j, n)` | `X` | … Effects: Constructs an empty container with at least `n` buckets, using `hasher()` as the hash function and `key_equal()` as the key equality predicate, and inserts elements from `[i, j)` into it. | Average case 𝒪(`n + N`) (`N` is `distance(i, j)`), worst case 𝒪(`n + N2`)
   > …

2. Modify 23.5.4.2 [unord.map.cnstr] p. 1-4 as indicated (The edits of p. 1 and p. 3 attempt to fix some editorial oversight.):

   >     explicit unordered_map(size_type n = see below,
   >                            const hasher& hf = hasher(),
   >                            const key_equal& eql = key_equal(),
   >                            const allocator_type& a = allocator_type());

   > > 1 Effects: Constructs an empty `unordered_map` using the specified hash function, key equality function, and allocator, and using at least `n` buckets. If `n` is not provided, the number of buckets is unspecified impldefdefault number of buckets in `unordered_map`. `max_load_factor()` returns `1.0`.

   > > 2 Complexity: Constant Linear in the number of buckets.

   >     template <class InputIterator>
   >     unordered_map(InputIterator f, InputIterator l,
   >                   size_type n = see below,
   >                   const hasher& hf = hasher(),
   >                   const key_equal& eql = key_equal(),
   >                   const allocator_type& a = allocator_type());

   > > 3 Effects: Constructs an empty `unordered_map` using the specified hash function, key equality function, and allocator, and using at least `n` buckets. If `n` is not provided, the number of buckets is unspecified impldefdefault number of buckets in `unordered_map`. Then inserts elements from the range `[f, l)`. `max_load_factor()` returns `1.0`.

   > > 4 Complexity: Average case linear, worst case quadratic Linear in the number of buckets. In the average case linear in `N` and in the worst case quadratic in `N` to insert the elements, where `N` is equal to number of elements in the range `[f,l)`.

3. Modify 23.5.5.2 [unord.multimap.cnstr] p. 1-4 as indicated (The edits of p. 1 and p. 3 attempt to fix some editorial oversight.):

   >     explicit unordered_multimap(size_type n = see below,
   >                                 const hasher& hf = hasher(),
   >                                 const key_equal& eql = key_equal(),
   >                                 const allocator_type& a = allocator_type());

   > > 1 Effects: Constructs an empty `unordered_multimap` using the specified hash function, key equality function, and allocator, and using at least `n` buckets. If `n` is not provided, the number of buckets is unspecified impldefdefault number of buckets in `unordered_multimap`. `max_load_factor()` returns `1.0`.

   > > 2 Complexity: Constant Linear in the number of buckets.

   >     template <class InputIterator>
   >     unordered_multimap(InputIterator f, InputIterator l,
   >                        size_type n = see below,
   >                        const hasher& hf = hasher(),
   >                        const key_equal& eql = key_equal(),
   >                        const allocator_type& a = allocator_type());

   > > 3 Effects: Constructs an empty `unordered_multimap` using the specified hash function, key equality function, and allocator, and using at least `n` buckets. If `n` is not provided, the number of buckets is unspecified impldefdefault number of buckets in `unordered_multimap`. Then inserts elements from the range `[f, l)`. `max_load_factor()` returns `1.0`.

   > > 4 Complexity: Average case linear, worst case quadratic Linear in the number of buckets. In the average case linear in `N` and in the worst case quadratic in `N` to insert the elements, where `N` is equal to number of elements in the range `[f,l)`.

4. Modify 23.5.6.2 [unord.set.cnstr] p. 1-4 as indicated (The edits of p. 1 and p. 3 attempt to fix some editorial oversight.):

   >     explicit unordered_set(size_type n = see below,
   >                            const hasher& hf = hasher(),
   >                            const key_equal& eql = key_equal(),
   >                            const allocator_type& a = allocator_type());

   > > 1 Effects: Constructs an empty `unordered_set` using the specified hash function, key equality function, and allocator, and using at least `n` buckets. If `n` is not provided, the number of buckets is unspecified impldefdefault number of buckets in `unordered_set`. `max_load_factor()` returns `1.0`.

   > > 2 Complexity: Constant Linear in the number of buckets.

   >     template <class InputIterator>
   >     unordered_set(InputIterator f, InputIterator l,
   >                   size_type n = see below,
   >                   const hasher& hf = hasher(),
   >                   const key_equal& eql = key_equal(),
   >                   const allocator_type& a = allocator_type());

   > > 3 Effects: Constructs an empty `unordered_set` using the specified hash function, key equality function, and allocator, and using at least `n` buckets. If `n` is not provided, the number of buckets is unspecified impldefdefault number of buckets in `unordered_set`. Then inserts elements from the range `[f, l)`. `max_load_factor()` returns `1.0`.

   > > 4 Complexity: Average case linear, worst case quadratic Linear in the number of buckets. In the average case linear in `N` and in the worst case quadratic in `N` to insert the elements, where `N` is equal to number of elements in the range `[f,l)`.

5. Modify 23.5.7.2 [unord.multiset.cnstr] p. 1-4 as indicated (The edits of p. 1 and p. 3 attempt to fix some editorial oversight.):

   >     explicit unordered_multiset(size_type n = see below,
   >                                 const hasher& hf = hasher(),
   >                                 const key_equal& eql = key_equal(),
   >                                 const allocator_type& a = allocator_type());

   > > 1 Effects: Constructs an empty `unordered_multiset` using the specified hash function, key equality function, and allocator, and using at least `n` buckets. If `n` is not provided, the number of buckets is unspecified impldefdefault number of buckets in `unordered_multiset`. `max_load_factor()` returns `1.0`.

   > > 2 Complexity: Constant Linear in the number of buckets.

   >     template <class InputIterator>
   >     unordered_multiset(InputIterator f, InputIterator l,
   >                        size_type n = see below,
   >                        const hasher& hf = hasher(),
   >                        const key_equal& eql = key_equal(),
   >                        const allocator_type& a = allocator_type());

   > > 3 Effects: Constructs an empty `unordered_multiset` using the specified hash function, key equality function, and allocator, and using at least `n` buckets. If `n` is not provided, the number of buckets is unspecified impldefdefault number of buckets in `unordered_multiset`. Then inserts elements from the range `[f, l)`. `max_load_factor()` returns `1.0`.

   > > 4 Complexity: Average case linear, worst case quadratic Linear in the number of buckets. In the average case linear in `N` and in the worst case quadratic in `N` to insert the elements, where `N` is equal to number of elements in the range `[f,l)`.

### 1213. Meaning of valid and singular iterator underspecified

Section: 24.2 [iterator.requirements] Status: Open Submitter: Daniel Krügler Opened: 2009-09-19 Last modified: 2014-02-20

View all other issues in [iterator.requirements].

View all issues with Open status.

Discussion:

The terms valid iterator and singular aren't properly defined. The fuzziness of those terms became even worse after the resolution of 208 (including further updates by 278). In 24.2 [iterator.requirements] as of N2723 the standard says now:

> 5 - These values are called past-the-end values. Values of an iterator `i` for which the expression `*i` is defined are called dereferenceable. The library never assumes that past-the-end values are dereferenceable. Iterators can also have singular values that are not associated with any container. [...] Results of most expressions are undefined for singular values; the only exceptions are destroying an iterator that holds a singular value and the assignment of a non-singular value to an iterator that holds a singular value. [...] Dereferenceable values are always non-singular.

> 10 - An invalid iterator is an iterator that may be singular.

First, issue 208 intentionally removed the earlier constraint that past-the-end values are always non-singular. The reason for this was to support null pointers as past-the-end iterators of e.g. empty sequences. But there seem to exist different views on what a singular (iterator) value is. E.g. according to the SGI definition a null pointer is not a singular value:

> Dereferenceable iterators are always nonsingular, but the converse is not true. For example, a null pointer is nonsingular (there are well defined operations involving null pointers) even thought it is not dereferenceable.

and proceeds:

> An iterator is valid if it is dereferenceable or past-the-end.

Even if the standard prefers a different meaning of singular here, the change was incomplete, because by restricting feasible expressions of singular iterators to destruction and assignment isn't sufficient for a past-the-end iterator: Of-course it must still be equality-comparable and in general be a readable value.

Second, the standard doesn't clearly say whether a past-the-end value is a valid iterator or not. E.g. 20.7.12 [specialized.algorithms]/1 says:

> In all of the following algorithms, the formal template parameter `ForwardIterator` is required to satisfy the requirements of a forward iterator (24.1.3) [..], and is required to have the property that no exceptions are thrown from [..], or dereference of valid iterators.

The standard should make better clear what "singular pointer" and "valid iterator" means. The fact that the meaning of a valid value has a core language meaning doesn't imply that for an iterator concept the term "valid iterator" has the same meaning.

Let me add a final example: In X [allocator.concepts.members] of N2914 we find:

>     pointer X::allocate(size_type n);

> > 11 Returns: a pointer to the allocated memory. [Note: if `n == 0`, the return value is unspecified. —end note]

> [..]

>     void X::deallocate(pointer p, size_type n);

> > Preconditions: `p` shall be a non-singular pointer value obtained from a call to `allocate()` on this allocator or one that compares equal to it.

If singular pointer value would include null pointers this make the preconditions unclear if the pointer value is a result of `allocate(0)`: Since the return value is unspecified, it could be a null pointer. Does that mean that programmers need to check the pointer value for a null value before calling deallocate?

[ 2010-11-09 Daniel comments: ]

A later paper is in preparation.

[ 2010 Batavia: ]

Doesn't need to be resolved for Ox

[2014-02-20 Re-open Deferred issues as Priority 4]

Proposed resolution:

Consider to await the paper.

### 1526. C++ should not impose thread safety requirements on C99 library implementations

Section: 17.6.5.9 [res.on.data.races] Status: Open Submitter: BSI Opened: 2011-03-24 Last modified: 2014-02-11

View all issues with Open status.

Discussion:

Addresses GB-111

Section 17.6.5.9 [res.on.data.races], Data Race Avoidance, requires the C++ Standard Library to avoid data races that might otherwise result from two threads making calls to C++ Standard Library functions on distinct objects. The C standard library is part of the C++ Standard Library and some C++ Standary library functions (parts of the Localization library, as well as Numeric Conversions in 21.5), are specified to make use of the C standard library. Therefore, the C++ standard indirectly imposes a requirement on the thread safety of the C standard library. However, since the C standard does not address the concept of thread safety conforming C implementations exist that do no provide such guarantees. This conflict needs to be reconciled.

Suggested resolution by national body comment:

> remove the requirement to make use of `strtol()` and `sprintf()` since these functions depend on the global C locale and thus cannot be made thread safe.

[2011-03-24 Madrid meeting]

Deferred

[ 2011 Bloomington ]

Alisdair: PJ, does this cause a problem in C?

PJ: Every implementation know of is thread safe.

Pete: There a couple of effects that are specified on strtol() and sprintf() which is a problem.

PJ: When C++ talks about C calls it should be "as if" calling the function.

Pete: Culprit is to string stuff. My fault.

PJ: Not your fault. You did what you were told. Distinct resolution to change wording.

Dietmar: What would we break if we change it back?

Pete: Nothing. If implemented on top of thread safe C library you are just fine.

Alisdair: Anyone want to clean up wording and put it back to what Pete gave us?

Alisdair: No volunteers. Do we want to mark as NAD? We could leave it as deferred.

Stefanus: Did original submitter care about this?

Lawrence: There is some work to make local calls thread safe. The resolution would be to call those thread safe version.

Pete: "As if called under single threaded C program"

Action Item (Alisdair): Write wording for this issue.

[2012, Kona]

Re-opened at the request of the concurrency subgroup, who feel there is an issue that needs clarifying for the (planned) 2017 standard.

Rationale:

No consensus to make a change at this time

[2012, Portland]

The concurrency subgroup decided to encourage the LWG to consider a change to 17.2 [library.c] or thereabouts to clarify that we are requiring C++-like thread-safety for `setlocale`, so that races are not introduced by C locale accesses, even when the C library allows it. This would require e.g. adding "and data race avoidance" at the end of 17.2 [library.c] p1:

"The C++ standard library also makes available the facilities of the C standard library, suitably adjusted to ensure static type safety and data race avoidance.",

with some further clarifications in the sections mentioned in 1526.

This seems to be consistent with existing implementations. This would technically not be constraining C implementation, but it would be further constraining C libraries used for both C and C++.

Proposed resolution:

This wording is relative to N3376.

1. Change 17.2 [library.c] p1 as indicated:

   > -1- The C++ standard library also makes available the facilities of the C standard library, suitably adjusted to ensure static type safety and data race avoidance.

### 2016. `Allocators` must be no-throw swappable

Section: 17.6.3.5 [allocator.requirements] Status: Ready Submitter: Daniel Krügler Opened: 2010-11-17 Last modified: 2014-02-15

View other active issues in [allocator.requirements].

View all other issues in [allocator.requirements].

View all issues with Ready status.

Discussion:

During the Batavia meeting it turned out that there is a definition hole for types satisfying the `Allocators` requirements: The problem became obvious when it was discussed whether all `swap` functions of `Containers` with internal data handles can be safely tagged with `noexcept` or not. While it is correct that the implicit `swap` function of an allocator is required to be a no-throw operation (because move/copy-constructors and assignment operators are required to be no-throw functions), there are no such requirements for specialized `swap` overloads for a particular allocator.

But this requirement is essential because the `Containers` are required to support swappable `Allocators`, when the value `allocator_traits<>::propagate_on_container_swap` evaluates to `true`.

[2011-02-10 Alberto, Daniel, and Pablo collaborated on the proposed wording]

The proposed resolution (based on N3225) attempts to solve the following problems:

1. Table 44 — Allocator requirements, expression rows `X::propagate_on_container_copy_assignment`, `X::propagate_on_container_move_assignment`, and `X::propagate_on_container_swap` only describe operations, but no requirements. In fact, if and only if these compile-time predicates evaluate to `true`, the additional requirements `CopyAssignable`, no-throw `MoveAssignable`, and no-throw lvalue `Swappable`, respectively, are imposed on the allocator types.
2. 23.2.1 [container.requirements.general] p. 9 misses to refer to the correct swap conditions: The current wording does not relate to 17.6.3.2 [swappable.requirements] as it should and omits to mention that lvalues shall be swapped. Additional there is one situation described twice in p. 8 and p. 9 (undefined behaviour unless `a.get_allocator() == b.get_allocator()` or `allocator_traits<allocator_type>::propagate_on_container_swap::value == true`), which should be cleaned up.

[2011-04-08 Pablo comments]

I'm implementing a version of list now and I actually do find it impossible to write an exception-safe assignment operator unless I can assume that allocator assignment does not throw. (The problem is that I use a sentinel node and I need to allocate a new sentinel using the new allocator without destroying the old one -- then swap the allocator and sentinel pointer in atomically, without risk of an exception leaving one inconsistent with the other.

Please update the proposed resolution to add the nothrow requirement to copy-assignment.

[2014-02-14 Issaquah: Move to Ready]

Fix a couple of grammar issues related to calling `swap` and move to Ready.

Proposed resolution:

1. Adapt the following three rows from Table 44 — Allocator requirements:

   > Table 44 — Allocator requirements
   > Expression | Return type | Assertion/note pre-/post-condition | Default
   > --- | --- | --- | ---
   > `X::propagate_on_container_copy_assignment` | Identical to or derived from `true_type` or `false_type` | `true_type` only if an allocator of type `X` should be copied when the client container is copy-assigned. See Note B, below. | `false_type`
   > `X::propagate_on_container_move_assignment` | Identical to or derived from `true_type` or `false_type` | `true_type` only if an allocator of type `X` should be moved when the client container is move-assigned. See Note B, below. | `false_type`
   > `X::propagate_on_container_swap` | Identical to or derived from `true_type` or `false_type` | `true_type` only if an allocator of type `X` should be swapped when the client container is swapped. See Note B, below. | `false_type`

2. Following 17.6.3.5 [allocator.requirements] p. 3 insert a new normative paragraph:

   > Note B: If `X::propagate_on_container_copy_assignment::value` is true, `X` shall satisfy the `CopyAssignable` requirements (Table 39 [copyassignable]) and the copy operation shall not throw exceptions. If `X::propagate_on_container_move_assignment::value` is true, `X` shall satisfy the `MoveAssignable` requirements (Table 38 [moveassignable]) and the move operation shall not throw exceptions. If `X::propagate_on_container_swap::value` is true, lvalues of `X` shall be swappable (17.6.3.2 [swappable.requirements]) and the `swap` operation shall not throw exceptions.

3. Modify 23.2.1 [container.requirements.general] p. 8 and p. 9 as indicated:

   > 8 - [..] The allocator may be replaced only via assignment or `swap()`. Allocator replacement is performed by copy assignment, move assignment, or swapping of the allocator only if `allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value`, `allocator_traits<allocator_type>::propagate_on_container_move_assignment::value`, or `allocator_traits<allocator_type>::propagate_on_container_swap::value` is true within the implementation of the corresponding container operation. The behavior of a call to a container's `swap` function is undefined unless the objects being swapped have allocators that compare equal or `allocator_traits<allocator_type>::propagate_on_container_swap::value` is true. In all container types defined in this Clause, the member `get_allocator()` returns a copy of the allocator used to construct the container or, if that allocator has been replaced, a copy of the most recent replacement.

   > 9 - The expression `a.swap(b)`, for containers `a` and `b` of a standard container type other than `array`, shall exchange the values of `a` and `b` without invoking any move, copy, or swap operations on the individual container elements. Lvalues of a Any `Compare`, `Pred`, or `Hash` objects types belonging to `a` and `b` shall be swappable and shall be exchanged by unqualified calls to non-member calling `swap` as described in 17.6.3.2 [swappable.requirements]. If `allocator_traits<allocator_type>::propagate_on_container_swap::value` is `true`, then lvalues of `allocator_type` shall be swappable and the allocators of `a` and `b` shall also be exchanged using an unqualified call to non-member by calling `swap` as described in 17.6.3.2 [swappable.requirements]. Otherwise, they the allocators shall not be swapped, and the behavior is undefined unless `a.get_allocator() == b.get_allocator()`. Every iterator referring to an element in one container before the swap shall refer to the same element in the other container after the swap. It is unspecified whether an iterator with value `a.end()` before the swap will have value `b.end()` after the swap.

### 2035. Output iterator requirements are broken

Section: 24.2.4 [output.iterators] Status: Open Submitter: Daniel Krügler Opened: 2011-02-27 Last modified: 2014-02-11

View other active issues in [output.iterators].

View all other issues in [output.iterators].

View all issues with Open status.

Discussion:

During the Pittsburgh meeting the proposal N3066 became accepted because it fixed several severe issues related to the iterator specification. But the current working draft (N3225) does not reflect all these changes. Since I'm unaware whether every correction can be done editorial, this issue is submitted to take care of that. To give one example: All expressions of Table 108 — "Output iterator requirements" have a post-condition that the iterator is incrementable. This is impossible, because it would exclude any finite sequence that is accessed by an output iterator, such as a pointer to a C array. The N3066 wording changes did not have these effects.

[2011-03-01: Daniel comments:]

This issue has some overlap with the issue 2038 and I would prefer if we could solve both at one location. I suggest the following approach:

1. The terms `dereferencable` and `incrementable` could be defined in a more general way not restricted to iterators (similar to the concepts `HasDereference` and `HasPreincrement` from working draft N2914). But on the other hand, all current usages of `dereferencable` and `incrementable` are involved with types that satisfy iterator requirements. Thus, I believe that it is sufficient for C++0x to add corresponding definitions to 24.2.1 [iterator.requirements.general] and to let all previous usages of these terms refer to this sub-clause. Since the same problem occurs with the past-the-end iterator, this proposal suggest providing similar references to usages that precede its definition as well.

2. We also need to ensure that all iterator expressions get either an operational semantics in terms of others or we need to add missing pre- and post-conditions. E.g. we have the following ones without semantics:

   >     *r++ = o // output iterator
   >     *r--     // bidirectional iterator

   According to the SGI specification these correspond to

   >     { *r = o; ++r; }                         // output iterator
   >     { reference tmp = *r; --r; return tmp; } // bidirectional iterator

   respectively. Please note especially the latter expression for bidirectional iterator. It fixes a problem that we have for forward iterator as well: Both these iterator categories provide stronger guarantees than input iterator, because the result of the dereference operation is `reference`, and not only convertible to the value type (The exact form from the SGI documentation does not correctly refer to `reference`).

[2011-03-14: Daniel comments and updates the suggested wording]

In addition to the before mentioned necessary changes there is another one need, which became obvious due to issue 2042: `forward_list<>::before_begin()` returns an iterator value which is not dereferencable, but obviously the intention is that it should be incrementable. This leads to the conclusion that imposing dereferencable as a requirement for the expressions `++r` is wrong: We only need the iterator to be incrementable. A similar conclusion applies to the expression `--r` of bidirectional iterators.

[ 2011 Bloomington ]

Consensus this is the correct direction, but there are (potentially) missing incrementable preconditions on some table rows, and the Remarks on when an output iterator becomes dereferencable are probably better handled outside the table, in a manner similar to the way we word for input iterators.

There was some concern about redundant pre-conditions when the operational semantic is defined in terms of operations that have preconditions, and a similar level of concern over dropping such redundancies vs. applying a consistent level of redundant specification in all the iterator tables. Wording clean-up in either direction would be welcome.

[2011-08-18: Daniel adapts the proposed resolution to honor the Bloomington request]

There is only a small number of further changes suggested to get rid of superfluous requirements and essentially non-normative assertions. Operations should not have extra pre-conditions, if defined by "in-terms-of" semantics, see e.g. `a != b` or `a->m` for Table 107. Further, some remarks, that do not impose anything or say nothing new have been removed, because I could not find anything helpful they provide. E.g. consider the remarks for Table 108 for the operations dereference-assignment and preincrement: They don't provide additional information say nothing surprising. With the new pre-conditions and post-conditions it is implied what the remarks intend to say.

[ 2011-11-03: Some observations from Alexander Stepanov via c++std-lib-31405 ]

The following sentence is dropped from the standard section on OutputIterators:

"In particular, the following two conditions should hold: first, any iterator value should be assigned through before it is incremented (this is, for an output iterator `i, i++; i++;` is not a valid code sequence); second, any value of an output iterator may have at most one active copy at any given time (for example, `i = j; *++i = a; *j = b;` is not a valid code sequence)."

[ 2011-11-04: Daniel comments and improves the wording ]

In regard to the first part of the comment, the intention of the newly proposed wording was to make clear that for the expression

>     *r = o

we have the precondition dereferenceable and the post-condition incrementable. And for the expression

>     ++r

we have the precondition incrementable and the post-condition dereferenceable or past-the-end. This should not allow for a sequence like `i++; i++;` but I agree that it doesn't exactly say that.

In regard to the second point: To make this point clearer, I suggest to add a similar additional wording as we already have for input iterator to the "Assertion/note" column of the expression `++r`:

"Post: any copies of the previous value of `r` are no longer required to be dereferenceable or incrementable."

The proposed has been updated to honor the observations of Alexander Stepanov.

Proposed resolution:

1. Add a reference to 24.2.1 [iterator.requirements.general] to the following parts of the library preceding Clause 24 Iterators library: (I stopped from 23.2.5 [unord.req] on, because the remaining references are the concrete containers)

   1. 17.6.3.2 [swappable.requirements] p5:

      > -5- A type `X` satisfying any of the iterator requirements (24.2) is `ValueSwappable` if, for any dereferenceable (24.2.1 [iterator.requirements.general]) object `x` of type `X`, `*x` is swappable.

   2. 17.6.3.5 [allocator.requirements], Table 27 — "Descriptive variable definitions", row with the expression `c`:

      > a dereferenceable (24.2.1 [iterator.requirements.general]) pointer of type `C*`

   3. 20.7.3.2 [pointer.traits.functions]:

      > Returns: The first template function returns a dereferenceable (24.2.1 [iterator.requirements.general]) pointer to `r` obtained by calling `Ptr::pointer_to(r)`; […]

   4. 21.4.3 [string.iterators] p. 2:

      > Returns: An iterator which is the past-the-end value (24.2.1 [iterator.requirements.general]).

   5. 22.4.5.1.2 [locale.time.get.virtuals] p. 11:

      >     iter_type do_get(iter_type s, iter_type end, ios_base& f,
      >       ios_base::iostate& err, tm *t, char format, char modifier) const;

      > > Requires: `t` shall be dereferenceable (24.2.1 [iterator.requirements.general]).

   6. 23.2.1 [container.requirements.general] p. 6:

      > […] `end()` returns an iterator which is the past-the-end (24.2.1 [iterator.requirements.general]) value for the container. […]

   7. 23.2.3 [sequence.reqmts] p. 3:

      > […] `q` denotes a valid dereferenceable (24.2.1 [iterator.requirements.general]) const iterator to `a`, […]

   8. 23.2.4 [associative.reqmts] p. 8 (I omit intentionally one further reference in the same sub-clause):

      > […] `q` denotes a valid dereferenceable (24.2.1 [iterator.requirements.general]) const iterator to `a`, […]

   9. 23.2.5 [unord.req] p. 10 (I omit intentionally one further reference in the same sub-clause):

      > […] `q` and `q1` are valid dereferenceable (24.2.1 [iterator.requirements.general]) const iterators to `a`, […]

2. Edit 24.2.1 [iterator.requirements.general] p. 5 as indicated (The intent is to properly define incrementable and to ensure some further library guarantee related to past-the-end iterator values):

   > -5- Just as a regular pointer to an array guarantees that there is a pointer value pointing past the last element of the array, so for any iterator type there is an iterator value that points past the last element of a corresponding sequence. These values are called past-the-end values. Values of an iterator `i` for which the expression `*i` is defined are called dereferenceable. Values of an iterator `i` for which the expression `++i` is defined are called incrementable. The library never assumes that past-the-end values are dereferenceable or incrementable. Iterators can also have singular values that are not associated with any sequence. […]

3. Modify the column contents of Table 106 — "Iterator requirements", 24.2.2 [iterator.iterators], as indicated:

   > Table 106 — Iterator requirements
   > Expression | Return type | Operational semantics | Assertion/note pre-/post-condition
   > --- | --- | --- | ---
   > `*r` | `reference` | `` | pre: `r` is dereferenceable.
   > `++r` | `X&` | `` | pre: `r` is incrementable.

4. Modify the column contents of Table 107 — "Input iterator requirements", 24.2.3 [input.iterators], as indicated [Rationale: The wording changes attempt to define a minimal "independent" set of operations, namely `*a` and `++r`, and to specify the semantics of the remaining ones. This approach seems to be in agreement with the original SGI specification — end rationale]:

   > Table 107 — Input iterator requirements (in addition to Iterator)
   > Expression | Return type | Operational semantics | Assertion/note pre-/post-condition
   > --- | --- | --- | ---
   > `a != b` | contextually convertible to `bool` | `!(a == b)` | pre: `(a, b)` is in the domain of `==`.
   > `*a` | convertible to `T` | `` | pre: `a` is dereferenceable. The expression `(void)*a, *a` is equivalent to `*a`. If `a == b` and `(a,b)` is in the domain of `==` then `*a` is equivalent to `*b`.
   > `a->m` | `` | `(*a).m` | pre: `a` is dereferenceable.
   > `++r` | `X&` | `` | pre: `r` is dereferenceable incrementable. post: `r` is dereferenceable or `r` is past-the-end. post: any copies of the previous value of `r` are no longer required either to be dereferenceable, incrementable, or to be in the domain of `==`.
   > `(void)r++` | `` | `(void)++r` | equivalent to `(void)++r`
   > `*r++` | convertible to `T` | `{ T tmp = *r; ++r; return tmp; }` | ``

5. Modify the column contents of Table 108 — "Output iterator requirements", 24.2.4 [output.iterators], as indicated [Rationale: The wording changes attempt to define a minimal "independent" set of operations, namely `*r = o` and `++r`, and to specify the semantics of the remaining ones. This approach seems to be in agreement with the original SGI specification — end rationale]:

   > Table 108 — Output iterator requirements (in addition to Iterator)
   > Expression | Return type | Operational semantics | Assertion/note pre-/post-condition
   > --- | --- | --- | ---
   > `*r = o` | result is not used | `` | pre: `r` is dereferenceable. Remark: After this operation `r` is not required to be dereferenceable and any copies of the previous value of `r` are no longer required to be dereferenceable or incrementable. post: `r` is incrementable.
   > `++r` | `X&` | `` | pre: `r` is incrementable. `&r == &++r`. Remark: After this operation `r` is not required to be dereferenceable. Remark: After this operation `r` is not required to be incrementable and any copies of the previous value of `r` are no longer required to be dereferenceable or incrementable. post: `r` is dereferenceable or `r` is past-the-end incrementable.
   > `r++` | convertible to `const X&` | `{ X tmp = r; ++r; return tmp; }` | Remark: After this operation `r` is not required to be dereferenceable. post: `r` is incrementable.
   > `*r++ = o` | result is not used | `{ *r = o; ++r; }` | Remark: After this operation `r` is not required to be dereferenceable. post: `r` is incrementable.

6. Modify the column contents of Table 109 — "Forward iterator requirements", 24.2.5 [forward.iterators], as indicated [Rationale: Since the return type of the expression `*r++` is now guaranteed to be type `reference`, the implied operational semantics from input iterator based on value copies is wrong — end rationale]

   > Table 109 — Forward iterator requirements (in addition to input iterator)
   > Expression | Return type | Operational semantics | Assertion/note pre-/post-condition
   > --- | --- | --- | ---
   > `r++` | convertible to `const X&` | `{ X tmp = r; ++r; return tmp; }` | ``
   > `*r++` | reference | `{ reference tmp = *r; ++r; return tmp; }` | ``

7. Modify the column contents of Table 110 — "Bidirectional iterator requirements", 24.2.6 [bidirectional.iterators], as indicated:

   > Table 110 — Bidirectional iterator requirements (in addition to forward iterator)
   > Expression | Return type | Operational semantics | Assertion/note pre-/post-condition
   > --- | --- | --- | ---
   > `--r` | `X&` | `` | pre: there exists `s` such that `r == ++s`. post: `r` is dereferenceable incrementable. `--(++r) == r`. `--r == --s` implies `r == s`. `&r == &--r`.
   > `r--` | convertible to `const X&` | `{ X tmp = r; --r; return tmp; }` | ``
   > `*r--` | reference | `{ reference tmp = *r; --r; return tmp; }` | ``

### 2038. Missing definition for `incrementable` iterator

Section: 24.2.4 [output.iterators] Status: Open Submitter: Pete Becker Opened: 2011-02-27 Last modified: 2014-02-11

View other active issues in [output.iterators].

View all other issues in [output.iterators].

View all issues with Open status.

Discussion:

In comp.lang.c++, Vicente Botet raises the following questions:

> "In "24.2.4 Output iterators" there are 3 uses of incrementable. I've not found the definition. Could some one point me where it is defined?

> Something similar occurs with dereferenceable. While the definition is given in "24.2.1 In general" it is used several times before.

> Shouldn't these definitions be moved to some previous section?"

He's right: both terms are used without being properly defined.

There is no definition of "incrementable".

While there is a definition of "dereferenceable", it is, in fact, a definition of "dereferenceable iterator". "dereferenceable" is used throughout Clause 23 (Containers) before its definition in Clause 24. In almost all cases it's referring to iterators, but in 17.6.3.2 [swappable.requirements] there is a mention of "dereferenceable object"; in 17.6.3.5 [allocator.requirements] the table of Descriptive variable definitions refers to a "dereferenceable pointer"; 20.7.3.2 [pointer.traits.functions] refers to a "dereferenceable pointer"; in 22.4.5.1.2 [locale.time.get.virtuals]/11 (`do_get`) there is a requirement that a pointer "shall be dereferenceable". In those specific cases it is not defined.

[2011-03-02: Daniel comments:]

I believe that the currently proposed resolution of issue 2035 solves this issue as well.

[ 2011 Bloomington ]

Agree with Daniel, this will be handled by the resolution of 2035.

Proposed resolution:

### 2051. Explicit `tuple` constructors for more than one parameter

Section: 20.4.2 [tuple.tuple], 20.4.2.1 [tuple.cnstr] Status: Open Submitter: Ville Voutilainen Opened: 2011-05-01 Last modified: 2014-02-11

View all other issues in [tuple.tuple].

View all issues with Open status.

Discussion:

One of my constituents wrote the following:

-------snip------------

So far the only use I've found for `std::tuple` is as an ad-hoc type to emulate multiple return values. If the tuple ctor was made non-explicit one could almost think C++ supported multiple return values especially when combined with `std::tie()`.

>     // assume types line_segment and point
>     // assume function double distance(point const&, point const&)

>     std::tuple<point, point>
>     closest_points(line_segment const& a, line_segment const& b) {
>      point ax;
>      point bx;
>      /* some math */

>      return {ax, bx};
>     }

>     double
>     distance(line_segment const& a, line_segment const& b) {
>      point ax;
>      point bx;
>      std::tie(ax, bx) = closest_points(a, b);

>      return distance(ax, bx);
>     }

-------snap----------

See also the messages starting from lib-29330.

Some notes:

1. `pair` allows such a return
2. a lambda with a deduced return type doesn't allow it for any type
3. `decltype` refuses `{1, 2}`

I would recommend making non-unary `tuple` constructors non-explicit.

[Bloomington, 2011]

Move to NAD Future, this would be an extension to existing functionality.

[Portland, 2012]

Move to Open at the request of the Evolution Working Group.

Proposed resolution:

### 2059. C++0x ambiguity problem with `map::erase`

Section: 23.4.4 [map] Status: Open Submitter: Christopher Jefferson Opened: 2011-05-18 Last modified: 2014-02-11

View all other issues in [map].

View all issues with Open status.

Discussion:

`map::erase` (and several related methods) took an iterator in C++03, but take a `const_iterator` in C++0x. This breaks code where the map's `key_type` has a constructor which accepts an iterator (for example a template constructor), as the compiler cannot choose between `erase(const key_type&)` and `erase(const_iterator)`.

>     #include <map>

>     struct X
>     {
>       template<typename T>
>       X(T&) {}
>     };

>     bool operator<(const X&, const X&) { return false; }

>     void erasor(std::map<X,int>& s, X x)
>     {
>       std::map<X,int>::iterator it = s.find(x);
>       if (it != s.end())
>         s.erase(it);
>     }

[ 2011 Bloomington ]

This issue affects only associative container `erase` calls, and is not more general, as these are the only functions that are also overloaded on another single arguement that might cause confusion - the `erase` by key method. The complete resolution should simply restore the `iterator` overload in addition to the `const_iterator` overload for all eight associative containers.

Proposed wording supplied by Alan Talbot, and moved to Review.

[2012, Kona]

Moved back to Open by post-meeting issues processing group.

Pablo very unhappy about case of breaking code with ambiguous conversion between both iterator types.

Alisdair strongly in favor of proposed resolution, this change from C++11 bit Chris in real code, and it took a while to track down the cause.

Move to open, bring in front of a larger group

Proposed wording from Jeremiah: `erase(key)` shall not participate in overload resolution if `iterator` is convertible to `key`. Note that this means making `erase(key)` a template-method

Poll Chris to find out if he already fixed his code, or fixed his library

Jeremiah - allow both overloads, but `enable_if` the `const_iterator` form as a template, requiring `is_same` to match only `const_iterator`.

Poll PJ to see if he has already applied this fix?

Proposed resolution:

Editorial note: The following things are different between 23.2.4 [associative.reqmts] p.8 and 23.2.5 [unord.req] p.10. These should probably be reconciled.

> 1. First uses the convention "denotes"; second uses the convention "is".
> 2. First redundantly says: "If no such element exists, returns a.end()." in erase table entry, second does not.

23.2.4 [associative.reqmts] Associative containers

8 In Table 102, `X` denotes an associative container class, `a` denotes a value of `X`, `a_uniq` denotes a value of `X` when `X` supports unique keys, `a_eq` denotes a value of `X` when `X` supports multiple keys, `u` denotes an identifier, `i` and `j` satisfy input iterator requirements and refer to elements implicitly convertible to `value_type`, `[i,j)` denotes a valid range, `p` denotes a valid const iterator to `a`, `q` denotes a valid dereferenceable const iterator to `a`, `r` denotes a valid dereferenceable iterator to a, `[q1, q2)` denotes a valid range of const iterators in `a`, `il` designates an object of type `initializer_list<value_type>`, `t` denotes a value of `X::value_type`, `k` denotes a value of `X::key_type` and `c` denotes a value of type `X::key_compare`. `A` denotes the storage allocator used by `X`, if any, or `std::allocator<X::value_type>` otherwise, and `m` denotes an allocator of a type convertible to `A`.

23.2.4 [associative.reqmts] Associative containers Table 102

Add row:

`a.erase(r)` | `iterator` | erases the element pointed to by `r`. Returns an iterator pointing to the element immediately following `r` prior to the element being erased. If no such element exists, returns `a.end()`. | amortized constant

23.2.5 [unord.req] Unordered associative containers

10 In table 103: `X` is an unordered associative container class, `a` is an object of type `X`, `b` is a possibly const object of type `X`, `a_uniq` is an object of type `X` when `X` supports unique keys, `a_eq` is an object of type `X` when `X` supports equivalent keys, `i` and `j` are input iterators that refer to `value_type`, `[i, j)` is a valid range, `p` and `q2` are valid const iterators to `a`, `q` and `q1` are valid dereferenceable const iterators to `a`, `r` is a valid dereferenceable iterator to a, `[q1,q2)` is a valid range in `a`, `il` designates an object of type `initializer_list<value_type>`, `t` is a value of type `X::value_type`, `k` is a value of type `key_type`, `hf` is a possibly const value of type `hasher`, `eq` is a possibly const value of type `key_equal`, `n` is a value of type `size_type`, and `z` is a value of type `float`.

23.2.5 [unord.req] Unordered associative containers Table 103

Add row:

`a.erase(r)` | `iterator` | Erases the element pointed to by `r`. Returns the iterator immediately following `r` prior to the erasure. | Average case O(1), worst case O(`a.size()`).

23.4.4.1 [map.overview] Class template map overview p. 2

    iterator erase(iterator position);
    iterator erase(const_iterator position);
    size_type erase(const key_type& x);
    iterator erase(const_iterator first, const_iterator last);

23.4.5.1 [multimap.overview] Class template multimap overview p. 2

    iterator erase(iterator position);
    iterator erase(const_iterator position);
    size_type erase(const key_type& x);
    iterator erase(const_iterator first, const_iterator last);

23.4.6.1 [set.overview] Class template set overview p. 2

    iterator erase(iterator position);
    iterator erase(const_iterator position);
    size_type erase(const key_type& x);
    iterator erase(const_iterator first, const_iterator last);

23.4.7.1 [multiset.overview] Class template multiset overview

    iterator erase(iterator position);
    iterator erase(const_iterator position);
    size_type erase(const key_type& x);
    iterator erase(const_iterator first, const_iterator last);

23.5.4.1 [unord.map.overview] Class template unordered_map overview p. 3

    iterator erase(iterator position);
    iterator erase(const_iterator position);
    size_type erase(const key_type& x);
    iterator erase(const_iterator first, const_iterator last);

23.5.5.1 [unord.multimap.overview] Class template unordered_multimap overview p. 3

    iterator erase(iterator position);
    iterator erase(const_iterator position);
    size_type erase(const key_type& x);
    iterator erase(const_iterator first, const_iterator last);

23.5.6.1 [unord.set.overview] Class template unordered_set overview p. 3

    iterator erase(iterator position);
    iterator erase(const_iterator position);
    size_type erase(const key_type& x);
    iterator erase(const_iterator first, const_iterator last);

23.5.7.1 [unord.multiset.overview] Class template unordered_multiset overview p. 3

    iterator erase(iterator position);
    iterator erase(const_iterator position);
    size_type erase(const key_type& x);
    iterator erase(const_iterator first, const_iterator last);

C.2.13 [diff.cpp03.containers] C.2.12 Clause 23: containers library

23.2.3, 23.2.4

Change: Signature changes: from iterator to const_iterator parameters

Rationale: Overspecification. Effects: The signatures of the following member functions changed from taking an iterator to taking a const_iterator:

- insert(iter, val) for vector, deque, list, set, multiset, map, multimap
- insert(pos, beg, end) for vector, deque, list, forward_list
- erase(iter) for set, multiset, map, multimap
- erase(begin, end) for set, multiset, map, multimap
- all forms of list::splice
- all forms of list::merge

Valid C++ 2003 code that uses these functions may fail to compile with this International Standard.

### 2062. Effect contradictions w/o no-throw guarantee of `std::function` swaps

Section: 20.9.11.2 [func.wrap.func], 20.9.11.2.2 [func.wrap.func.mod] Status: Open Submitter: Daniel Krügler Opened: 2011-05-28 Last modified: 2014-05-02

View other active issues in [func.wrap.func].

View all other issues in [func.wrap.func].

View all issues with Open status.

Discussion:

Howard Hinnant observed in reflector message c++std-lib-30841 that 20.9.11.2 [func.wrap.func] makes the member swap `noexcept`, even though the non-member swap is not `noexcept`.

The latter was an outcome of the discussions during the Batavia meeting and the Madrid meeting involving LWG 1349, which seems to indicate that the remaining `noexcept` specifier at the member swap is incorrect and should be removed.

But if we allow for a potentially throwing member swap of `std::function`, this causes another conflict with the exception specification for the following member function:

>     template<class F> function& operator=(reference_wrapper<F> f) noexcept;

> > Effects: `function(f).swap(*this);`

Note that in this example the sub-expression `function(f)` does not cause any problems, because of the nothrow-guarantee given in 20.9.11.2.1 [func.wrap.func.con] p. 10. The problem is located in the usage of the swap which could potentially throw given the general latitude.

So, either the Madrid meeting decision need to be revised (and both member and free swap of `std::function` should be noexcept), or this function needs to be adapted as well, e.g. by taking the exception-specification away or by changing the semantics.

One argument for "swap-may-throw" would be to allow for small-object optimization techniques where the copy of the target may throw. But given the fact that the swap function has been guaranteed to be "Throws: Nothing" from TR1 on, it seems to me that that there would still be opportunities to perform small-object optimizations just restricted to the set of target copies that cannot throw.

In my opinion member swap of `std::function` has always been intended to be no-throw, because otherwise there would be no good technical reason to specify the effects of several member functions in terms of the "construct-swap" idiom (There are three functions that are defined this way), which provides the strong exception safety in this case. I suggest to enforce that both member swap and non-member swap of `std::function` are nothrow functions as it had been guaranteed since TR1 on.

[ 2011 Bloomington ]

Dietmar: May not be swappable in the first place.

Alisdair: This is wide contact. Then we should be taking noexcept off instead of putting it on. This is preferred resolution.

Pablo: This is bigger issue. Specification of assignment in terms of swap is suspect to begin with. It is over specification. How this was applied to string is a better example to work from.

Pablo: Two problems: inconsistency that should be fixed (neither should have noexcept), the other issues is that assignment should not be specified in terms of swap. There are cases where assignment should succeed where swap would fail. This is easier with string as it should follow container rules.

Action Item (Alisdair): There are a few more issues found to file.

Dave: This is because of allocators? The allocator makes this not work.

Howard: There is a type erased allocator in shared_ptr. There is a noexcept allocator in shared_ptr.

Pablo: shared_ptr is a different case. There are shared semantics and the allocator does move around. A function does not have shared semantics.

Alisdair: Function objects think they have unique ownership.

Howard: In function we specify semantics with copy construction and swap.

Action Item (Pablo): Write this up better (why assignment should not be defined in terms of swap)

Howard: Not having trouble making function constructor no throw.

Dietmar: Function must allocate memory.

Howard: Does not put stuff that will throw on copy or swap in small object optimization. Put those on heap. Storing allocator, but has to be no throw copy constructable.

Pablo: Are you allowed to or required to swap or move allocators in case or swap or move.

Dave: An allocator that is type erased should be different...

Pablo: it is

Dave: Do you need to know something about allocator types? But only at construction time.

Pablo: You could have allocators that are different types.

Dave: Swap is two ended operation.

Pablo: Opinion is that both have to say propagate on swap for them to swap.

John: It is not arbitrary. If one person says no. No is no.

Howard: Find noexcept swap to be very useful. Would like to move in that direction and bring container design along.

Dave: If you have something were allocator must not propagate you can detect that at construction time.

...

Pablo: Need to leave this open and discuss in smaller group.

Alisdair: Tried to add boost::any as TR2 proposal and ran into this issue. Only the first place where we run into issues with type erased allocators. Suggest we move it to open.

Action Item: Move to open.

Action Item (Pablo works with Howard and Daniel): Address the more fundamental issue (which may be multiple issues) and write up findings.

[ Original resolution: ]

This wording is relative to the FDIS.

1. Modify the header `<functional>` synopsis in 20.9 [function.objects] as indicated:

   >     namespace std {
   >       […]

   >       template<class R, class... ArgTypes>
   >       void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&) noexcept;

   >       […]
   >     }

2. Modify the class template `function` synopsis in 20.9.11.2 [func.wrap.func] as indicated:

   >     namespace std {
   >       […]

   >       // [func.wrap.func.alg], specialized algorithms:
   >       template<class R, class... ArgTypes>
   >       void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&) noexcept;

   >       […]
   >     }

3. Modify 20.9.11.2.7 [func.wrap.func.alg] as indicated:

   >     template<class R, class... ArgTypes>
   >     void swap(function<R(ArgTypes...)>& f1, function<R(ArgTypes...)>& f2) noexcept;

   > > -1- Effects: `f1.swap(f2);`

[2014-02-28 (Post Issaquah), Pablo provides more information]

For cross-referencing purposes: The resolution of this issue should be harmonized with any resolution to LWG 2370, which addresses inappropriate `noexcept`s in some function constructors.

We have the following choices:

1. `swap()` does not throw

   > Discussion: This definition is desirable, and allows assignment to be implemented with the strong exception guarantee, but it does have consequences: The implementation cannot use the small-object optimization for a function-object `F` unless `F` is `NothrowMovable` (nothrow-swappable is unimportant because `F` is not swapped with another `F`). Note that many functors written before C++11 will not have move constructors decorated with `noexcept`, so this limitation could affect a lot of code.

   > It is not clear what other implementation restrictions might be needed. Allocators are required not to throw on move or copy. Is that sufficient?

2. `swap()` can throw

   > Discussion: This definition gives maximum latitude to implementation to use small-object optimization. However, the strong guarantee on assignment is difficult to achieve. Should we consider giving up on the strong guarantee? How much are we willing to pessimize code for exceptions?

3. `swap()` will not throw if both functions have `NoThrowMoveable` functors

   > Discussion: This definition is similar to option 2, but gives slightly stronger guarantees. Here, `swap()` can throw, but the programmer can theoretically prevent that from happening. This should be straight-forward to implement and gives the implementation a lot of latitude for optimization. However, because this is a dynamic decision, the program is not as easy to reason about. Also, the strong guarantee for assignment is compromized as in option 2.

Proposed resolution:

### 2063. Contradictory requirements for string move assignment

Section: 21.4 [basic.string] Status: Open Submitter: Howard Hinnant Opened: 2011-05-29 Last modified: 2014-02-11

View other active issues in [basic.string].

View all other issues in [basic.string].

View all issues with Open status.

Discussion:

21.4.1 [string.require]/p4 says that `basic_string` is an "allocator-aware" container and behaves as described in 23.2.1 [container.requirements.general].

23.2.1 [container.requirements.general] describes move assignment in p7 and Table 99.

If `allocator_traits<allocator_type>::propagate_on_container_move_assignment::value` is false, and if the allocators stored in the lhs and rhs sides are not equal, then move assigning a string has the same semantics as copy assigning a string as far as resources are concerned (resources can not be transferred). And in this event, the lhs may have to acquire resources to gain sufficient capacity to store a copy of the rhs.

However 21.4.2 [string.cons]/p22 says:

>     basic_string<charT,traits,Allocator>&
>     operator=(basic_string<charT,traits,Allocator>&& str) noexcept;

> > Effects: If `*this` and `str` are not the same object, modifies `*this` as shown in Table 71. [Note: A valid implementation is `swap(str)`. — end note ]

These two specifications for `basic_string::operator=(basic_string&&)` are in conflict with each other. It is not possible to implement a `basic_string` which satisfies both requirements.

Additionally assign from an rvalue `basic_string` is defined as:

>     basic_string& assign(basic_string&& str) noexcept;

> > Effects: The function replaces the string controlled by `*this` with a string of length `str.size()` whose elements are a copy of the string controlled by `str`. [ Note: A valid implementation is `swap(str)`. — end note ]

It seems contradictory that this member can be sensitive to `propagate_on_container_swap` instead of `propagate_on_container_move_assignment`. Indeed, there is a very subtle chance for undefined behavior here: If the implementation implements this in terms of `swap`, and if `propagate_on_container_swap` is false, and if the two allocators are unequal, the behavior is undefined, and will likely lead to memory corruption. That's a lot to go wrong under a member named "assign".

[ 2011 Bloomington ]

Alisdair: Can this be conditional noexcept?

Pablo: We said we were not going to put in many conditional noexcepts. Problem is not allocator, but non-normative definition. It says swap is a valid operation which it is not.

Dave: Move assignment is not a critical method.

Alisdair: Was confusing assignment and construction.

Dave: Move construction is critical for efficiency.

Kyle: Is it possible to test for noexcept.

Alisdair: Yes, query the noexcept operator.

Alisdair: Agreed there is a problem that we cannot unconditionally mark these operations as noexcept.

Pablo: How come swap is not defined in alloc

Alisdair: It is in utility.

Pablo: Swap has a conditional noexcept. Is no throw move constructable, is no throw move assignable.

Pablo: Not critical for strings or containers.

Kyle: Why?

Pablo: They do not use the default swap.

Dave: Important for deduction in other types.

Alisdair: Would change the policy we adopted during FDIS mode.

Pablo: Keep it simple and get some vendor experience.

Alisdair: Is this wording correct? Concerned with bullet 2.

Pablo: Where does it reference containers section.

Alisdair: String is a container.

Alisdair: We should not remove redundancy piecemeal.

Pablo: I agree. This is a deviation from rest of string. Missing forward reference to containers section.

Pablo: To fix section 2. Only the note needs to be removed. The rest needs to be a forward reference to containers.

Alisdair: That is a new issue.

Pablo: Not really. Talking about adding one sentence, saying that basic string is a container.

Dave: That is not just a forward reference, it is a semantic change.

PJ: We intended to make it look like a container, but it did not satisfy all the requirements.

Pablo: Clause 1 is correct. Clause 2 is removing note and noexcept (do not remove the rest). Clause 3 is correct.

Alisdair: Not sure data() is correct (in clause 2).

Conclusion: Move to open, Alisdair and Pablo volunteered to provide wording

[ originally proposed wording: ]

This wording is relative to the FDIS.

1. Modify the class template `basic_string` synopsis in 21.4 [basic.string]:

   >     namespace std {
   >       template<class charT, class traits = char_traits<charT>,
   >         class Allocator = allocator<charT> >
   >       class basic_string {
   >       public:
   >         […]
   >         basic_string& operator=(basic_string&& str) noexcept;
   >         […]
   >         basic_string& assign(basic_string&& str) noexcept;
   >         […]
   >       };
   >     }

2. Remove the definition of the `basic_string` move assignment operator from 21.4.2 [string.cons] entirely, including Table 71 — `operator=(const basic_string<charT, traits, Allocator>&&)`. This is consistent with how we define move assignment for the containers in Clause 23:

   >     basic_string<charT,traits,Allocator>&
   >     operator=(basic_string<charT,traits,Allocator>&& str) noexcept;

   > > -22- Effects: If `*this` and `str` are not the same object, modifies `*this` as shown in Table 71. [ Note: A valid implementation is `swap(str)`. — end note ]

   > > -23- If `*this` and `str` are the same object, the member has no effect.

   > > -24- Returns: `*this`

   > Table 71 — `operator=(const basic_string<charT, traits, Allocator>&&)`
   > Element | Value
   > --- | ---
   > `data()` | points at the array whose first element was pointed at by `str.data()`
   > `size()` | previous value of `str.size()`
   > `capacity()` | a value at least as large as `size()`

3. Modify the paragraphs prior to 21.4.6.3 [string::assign] p.3 as indicated (The first insertion recommends a separate paragraph number for the indicated paragraph):

   >     basic_string& assign(basic_string&& str) noexcept;

   > > -?- Effects: Equivalent to `*this = std::move(str)`. The function replaces the string controlled by `*this` with a string of length `str.size()` whose elements are a copy of the string controlled by `str`. [ Note: A valid implementation is `swap(str)`. — end note ]

   > > -3- Returns: `*this`

[ 2012-08-11 Joe Gottman observes: ]

> One of the effects of `basic_string`'s move-assignment operator (21.4.2 [string.cons], Table 71) is

> > Element | Value
> > --- | ---
> > `data()` | points at the array whose first element was pointed at by `str.data()`

> If a string implementation uses the small-string optimization and the input string `str` is small enough to make use of it, this effect is impossible to achieve. To use the small string optimization, a string has to be implemented using something like

> >     union
> >     {
> >        char buffer[SMALL_STRING_SIZE];
> >        char *pdata;
> >     };

> When the string is small enough to fit inside `buffer`, the `data()` member function returns `static_cast<const char *>(buffer)`, and since `buffer` is an array variable, there is no way to implement move so that the moved-to string's `buffer` member variable is equal to `this->buffer`.

> Resolution proposal:

> Change Table 71 to read:

> > Element | Value
> > --- | ---
> > `data()` | points at the array whose first element was pointed at by `str.data()` that contains the same characters in the same order as `str.data()` contained before `operator=()` was called

Proposed resolution:

### 2070. `allocate_shared` should use `allocator_traits<A>::construct`

Section: 20.8.2.2.6 [util.smartptr.shared.create] Status: Open Submitter: Jonathan Wakely Opened: 2011-07-11 Last modified: 2014-05-02

View all issues with Open status.

Discussion:

20.8.2.2.6 [util.smartptr.shared.create] says:

> -2- Effects: Allocates memory suitable for an object of type `T` and constructs an object in that memory via the placement new expression `::new (pv) T(std::forward<Args>(args)...)`. The template `allocate_shared` uses a copy of a to allocate memory. If an exception is thrown, the functions have no effect.

This explicitly requires placement new rather than using `allocator_traits<A>::construct(a, (T*)pv, std::forward<Args>(args)...)` In most cases that would result in the same placement new expression, but would allow more control over how the object is constructed e.g. using `scoped_allocator_adaptor` to do uses-allocator construction, or using an allocator declared as a friend to construct objects with no public constructors.

[ 2011-08-16 Bloomington: ]

Agreed to fix in principle, but believe that `make_shared` and `allocate_shared` have now diverged enough that their descriptions should be separated. Pablo and Stefanus to provide revised wording.

Daniel's (old) proposed resolution:

> This wording is relative to the FDIS.

> 1. Change the following paragraphs of 20.8.2.2.6 [util.smartptr.shared.create] as indicated (The suggested removal of the last sentence of p1 is not strictly required to resolve this issue, but is still recommended, because it does not say anything new but may give the impression that it says something new):

>    >     template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args);
>    >     template<class T, class A, class... Args>
>    >       shared_ptr<T> allocate_shared(const A& a, Args&&... args);

>    > > -1- Requires: For the template `make_shared`, t The expression `::new (pv) T(std::forward<Args>(args)...)`, where `pv` has type `void*` and points to storage suitable to hold an object of type `T`, shall be well formed. For the template `allocate_shared`, the expression `allocator_traits<A>::construct(a, pt, std::forward<Args>(args)...)`, where `pt` has type `T*` and points to storage suitable to hold an object of type `T`, shall be well formed. `A` shall be an allocator ([allocator.requirements]). The copy constructor and destructor of `A` shall not throw exceptions.

>    > > -2- Effects: Allocates memory suitable for an object of type `T` and constructs an object in that memory. The template `make_shared` constructs the object via the placement new expression `::new (pv) T(std::forward<Args>(args)...)`. The template `allocate_shared` uses a copy of `a` to allocate memory and constructs the object by calling `allocator_traits<A>::construct(a, pt, std::forward<Args>(args)...)`. If an exception is thrown, the functions have no effect.

>    > > -3- Returns: A `shared_ptr` instance that stores and owns the address of the newly constructed object of type `T`.

>    > > -4- Postconditions: `get() != 0 && use_count() == 1`

>    > > -5- Throws: `bad_alloc`, or, for the template `make_shared`, an exception thrown from the constructor of `T`, or, for the template `allocate_shared`, an exception thrown from `A::allocate` or from `allocator_traits<A>::construct` from the constructor of `T`.

>    > > -6- Remarks: Implementations are encouraged, but not required, to perform no more than one memory allocation. [ Note: This provides efficiency equivalent to an intrusive smart pointer. — end note ]

>    > > -7- [ Note: These functions will typically allocate more memory than `sizeof(T)` to allow for internal bookkeeping structures such as the reference counts. — end note ]

[2011-12-04: Jonathan and Daniel improve wording]

See also c++std-lib-31796

[2013-10-13, Ville]

This issue is related to 2089.

[2014-02-15 post-Issaquah session : move to Tentatively NAD]

STL: This takes an allocator, but then ignores its construct. That's squirrely.

Alisdair: The convention is when you take an allocator, you use its construct.

STL: 23.2.1 [container.requirements.general]/3, argh! This fills me with despair, but I understand it now.

STL: Ok, this is some cleanup.

STL: You're requiring `b` to be of type `A` and not being rebound, is that an overspecification?

Pablo: Good point. Hmm, that's only a requirement on what must be well-formed.

STL: If it's just a well-formed requirement, then why not just use a directly?

Pablo: Yeah, the well-formed requirement is overly complex. It's not a real call, we could just use a directly. It makes it harder to read.

Alisdair: `b` should be an allocator in the same family as `a`.

Pablo: This is a well-formed requirement, I wonder if it's the capital A that's the problem here. It doesn't matter here, this is way too much wording.

Alisdair: It's trying to tie the constructor arguments into the allocator requirements.

Pablo: `b` could be struck, that's a runtime quality. The construct will work with anything that's in the family of `A`.

Alisdair: The important part is the `forward` of `Args`.

Pablo: `A` must be an allocator, and `forward` `Args` must work with that.

Alisdair: First let's nail down `A`.

Pablo: Then replace `b` with `a`, and strike the rest.

STL: You need `pt`'s type, at least.

Pablo: There's nothing to be said about runtime constraints here, this function doesn't even take a `pt`.

STL: Looking at the Effects, I believe `b` is similarly messed up, we can use `a2` to construct an object.

Alisdair: Or any allocator in the family of `a`.

STL: We say this stuff for the deallocate too, it should be lifted up.

STL: "owns the address" is weird.

Alisdair: shared_ptr owns pointers, although it does sound funky.

Walter: "to destruct" is ungrammatical.

STL: "When ownership is given up" is not what we usually say.

Alisdair: I think the Returns clause is the right place to say this.

STL: The right place to say this is `shared_ptr`'s dtor, we don't want to use Core's "come from" convention.

Alisdair: I'm on the hook to draft cleaner wording.

Proposed resolution:

This wording is relative to the FDIS.

1. Change the following paragraphs of 20.8.2.2.6 [util.smartptr.shared.create] as indicated:

   >     template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args);
   >     template<class T, class A, class... Args>
   >       shared_ptr<T> allocate_shared(const A& a, Args&&... args);

   -1- Requires: The expression `::new (pv) T(std::forward<Args>(args)...)`, where `pv` has type `void*` and points to storage suitable to hold an object of type `T`, shall be well formed. `A` shall be an allocator (17.6.3.5 [allocator.requirements]). The copy constructor and destructor of `A` shall not throw exceptions.

   -2- Effects: Equivalent to

   >     return allocate_shared<T>(allocator<T>(), std::forward<Args>(args)...);

   Allocates memory suitable for an object of type `T` and constructs an object in that memory via the placement new expression `::new (pv) T(std::forward<Args>(args)...)`. The template `allocate_shared` uses a copy of `a` to allocate memory. If an exception is thrown, the functions have no effect.

   -?- Remarks: An implementation may meet the effects (and the implied guarantees) without creating the allocator object [Note: That is, user-provided specializations of `std::allocator` may not be instantiated, the expressions `::new (pv) T(std::forward<Args>(args)...)` and `pv->~T()` may be evaluated directly — end note].

   -3- Returns: A `shared_ptr` instance that stores and owns the address of the newly constructed object of type `T`.

   -4- Postconditions: `get() != 0 && use_count() == 1`

   -5- Throws: `bad_alloc`, or an exception thrown from `A::allocate` or from the constructor of `T`.

   -6- Remarks: Implementations are encouraged, but not required, to perform no more than one memory allocation. [Note: This provides efficiency equivalent to an intrusive smart pointer. — end note]

   -7- [Note: These functions will typically allocate more memory than `sizeof(T)` to allow for internal bookkeeping structures such as the reference counts. — end note]

2. Add the following set of new paragraphs immediately following the previous paragraph 7 of 20.8.2.2.6 [util.smartptr.shared.create]:

   >     template<class T, class A, class... Args>
   >       shared_ptr<T> allocate_shared(const A& a, Args&&... args);

   -?- Requires: The expressions `allocator_traits<A>::construct(b, pt, std::forward<Args>(args)...)` and `allocator_traits<A>::destroy(b, pt)` shall be well-formed and well-defined, where `b` has type `A` and is a copy of `a` and where `pt` has type `T*` and points to storage suitable to hold an object of type `T`. `A` shall meet the allocator requirements (17.6.3.5 [allocator.requirements]).

   -?- Effects: Uses an object `a2` of type `allocator_traits<A>::rebind_alloc<unspecified>` that compares equal to `a` to allocate memory suitable for an object of type `T`. Uses a copy `b` of type `A` from `a` to construct an object of type `T` in that memory by calling `allocator_traits<A>::construct(b, pt, std::forward<Args>(args)...)`. If an exception is thrown, the function has no effect.

   -?- Returns: A `shared_ptr` instance that stores and owns the address of the newly constructed object of type `T`. When ownership is given up, the effects are as follows: Uses a copy `b2` of type `A` from `a` to destruct an object of type `T` by calling `allocator_traits<A>::destroy(b2, pt2)` where `pt2` has type `T*` and refers to the newly constructed object. Then uses an object of type `allocator_traits<A>::rebind_alloc<unspecified>` that compares equal to `a` to deallocate the allocated memory.

   -?- Postconditions: `get() != 0 && use_count() == 1`

   -?- Throws: Nothing unless memory allocation or `allocator_traits<A>::construct` throws an exception.

   -?- Remarks: Implementations are encouraged, but not required, to perform no more than one memory allocation. [Note: Such an implementation provides efficiency equivalent to an intrusive smart pointer. — end note]

   -?- [Note: This function will typically allocate more memory than `sizeof(T)` to allow for internal bookkeeping structures such as the reference counts. — end note]

### 2072. Unclear wording about capacity of temporary buffers

Section: 20.7.11 [temporary.buffer] Status: Open Submitter: Kazutoshi Satoda Opened: 2011-08-10 Last modified: 2014-05-23

View all other issues in [temporary.buffer].

View all issues with Open status.

Discussion:

According to 20.7.11 [temporary.buffer] p1+2:

>     template <class T>
>     pair<T*, ptrdiff_t> get_temporary_buffer(ptrdiff_t n) noexcept;

> > -1- Effects: Obtains a pointer to storage sufficient to store up to `n` adjacent `T` objects. It is implementation-defined whether over-aligned types are supported (3.11).

> > -2- Returns: A pair containing the buffer's address and capacity (in the units of `sizeof(T)`), or a pair of 0 values if no storage can be obtained or if `n <= 0`.

I read this as prohibiting to return a buffer of which capacity is less than `n`, because such a buffer is not sufficient to store `n` objects.

The corresponding description in SGI STL is clear on this point, but I think it is a bit too verbose:

> (for the return value, a pair `P`) [...] the buffer pointed to by `P.first` is large enough to hold `P.second` objects of type `T`. `P.second` is greater than or equal to 0, and less than or equal to `len`.

There seems to be two different targets of the "up to n" modification: The capacity of obtained buffer, and the actual number that the caller will store into the buffer.

First I read as the latter, and got surprised seeing that libstdc++ implementation can return a smaller buffer. I started searching about `get_temporary_buffer()`. After reading a quote from TC++PL at stackoverflow, I realized that the former is intended.

Such misinterpretation seems common:

- The above question is likely started from same misinterpretation.

- JIS standard (Japanese translation of ISO/IEC standard) says nothing like "up to". I think the editor misinterpreted the original wording, and omitted words for "up to" as it is redundant. (If a buffer is sufficient to store `n` objects, it is also sufficient to store up to `n` objects.)

- Rogue Wave implementation doesn't return smaller buffer, instead, it can return larger buffer on some circumstances. Apache STDCXX is a derived version of that implementation, and publicly accessible:

  > Specializations of the `get_temporary_buffer()` function template attempt to allocate a region of storage sufficiently large to store at least `n` adjacent objects of type `T`.

  I know one commercial compiler package based on Rogue Wave implementation, and its implementation is essentially same as the above.

[2014-05-18, Daniel comments and suggests concrete wording]

The provided wording attempts to clarify the discussed capacity freedom, but it also makes it clearer that the returned memory is just "raw memory", which is currently not really clear. In addition the wording clarifies that the deallocating `return_temporary_buffer` function does not throw exceptions, which I believe is the intention when the preconditions of the functions are satisfied. Then, my understanding is that we can provide to `return_temporary_buffer` a null pointer value if that was the value, `get_temporary_buffer()` had returned. Furthermore, as STL noticed, the current wording seemingly allows multiple invocations of `return_temporary_buffer` with the same value returned by `get_temporary_buffer`; this should be constrained similar to the wording we have for `operator delete` (unfortunately we miss such wording for allocators).

Proposed resolution:

This wording is relative to N3936.

1. Change 20.7.11 [temporary.buffer] as indicated:

   >     template <class T>
   >       pair<T*, ptrdiff_t> get_temporary_buffer(ptrdiff_t n) noexcept;

   > > -1- Effects: Obtains a pointer to uninitialized, contiguous storage for `N` adjacent objects of type `T`, for some non-negative number `N`.Obtains a pointer to storage sufficient to store up to `n` adjacent `T` objects. It is implementation-defined whether over-aligned types are supported (3.11).

   > > -?- Remarks: Calling `get_temporary_buffer` with a positive number `n` is a non-binding request to return storage for `n` objects of type `T`. In this case, an implementation is permitted to return instead storage for a non-negative number `N` of such objects, where `N != n` (including `N == 0`). [Note: The request is non-binding to allow latitude for implementation-specific optimizations of its memory management. — end note].

   > > -2- Returns: If `n <= 0` or if no storage could be obtained, returns a pair `P` such that `P.first` is a null pointer value and `P.second == 0`; otherwise returns a pair `P` such that `P.first` refers to the address of the uninitialized storage and `P.second` refers to its capacity `N` (in the units of `sizeof(T)`).A `pair` containing the buffer's address and capacity (in the units of `sizeof(T)`), or a pair of 0 values if no storage can be obtained or if `n <= 0`.

   >     template <class T> void return_temporary_buffer(T* p);

   > > -3- Effects: Deallocates the buffer to which `p` points storage referenced by `p`.

   > > -4- Requires: The buffer shall have been previously allocated by `p` shall be a pointer value returned by an earlier call to `get_temporary_buffer` which has not been invalidated by an intervening call to `return_temporary_buffer(T*)`.

   > > -?- Throws: Nothing.

### 2076. Bad `CopyConstructible` requirement in set constructors

Section: 23.4.6.2 [set.cons] Status: New Submitter: Jens Maurer Opened: 2011-08-20 Last modified: 2014-06-17

View all issues with New status.

Discussion:

23.4.6.2 [set.cons] paragraph 4 says:

> Requires: If the iterator's dereference operator returns an lvalue or a non-const rvalue, then `Key` shall be `CopyConstructible`.

I'm confused why a "non-const rvalue" for the return value of the iterator would require `CopyConstructible`; isn't that exactly the situation when you'd want to apply the move constructor?

The corresponding requirement for `multimap` seems better in that regard ([multimap.cons] paragraph 3):

> Requires: If the iterator's dereference operator returns an lvalue or a const rvalue `pair<key_type, mapped_type>`, then both `key_type` and mapped_type shall be `CopyConstructible`.

Obviously, if I have a const rvalue, I can't apply the move constructor (which will likely attempt modify its argument).

Dave Abrahams:

I think you are right. Proposed resolution: drop "non-" from 23.4.6.2 [set.cons] paragraph 3.

[2012, Kona]

The wording is in this area will be affected by Pablo's paper being adopted at this meeting. Wait for that paper to be applied before visiting this issue - deliberately leave in New status until the next meeting.

Proposed resolution from Kona 2012:

> This wording is relative to the FDIS.

> Change 23.4.6.2 [set.cons] p3 as follows:

> >     template <class InputIterator>
> >       set(InputIterator first, InputIterator last,
> >         const Compare& comp = Compare(), const Allocator& = Allocator());

> > > -3- Effects: Constructs an empty set using the specified comparison object and allocator, and inserts elements from the range [`first,last`).

> > > -4- Requires: If the iterator's dereference operator returns an lvalue or a non-const rvalue, then `Key` shall be `CopyConstructible`.

> > > -5- Complexity: Linear in `N` if the range [`first,last`) is already sorted using `comp` and otherwise `N logN`, where `N` is `last - first`.

[2014-05-18, Daniel comments]

According to Pablo, the current P/R correctly incorporates the changes from his paper (which was adopted in Kona)

[2014-06-10, STL comments and suggests better wording]

N1858 was voted into WP N2284 but was "(reworded)", introducing the "non-const" damage.

N1858 wanted to add this for map:

> Requires: Does not require `CopyConstructible` of either `key_type` or `mapped_type` if the dereferenced `InputIterator` returns a non-const rvalue `pair<key_type, mapped_type>`. Otherwise `CopyConstructible` is required for both `key_type` and `mapped_type`.

And this for set:

> Requires: `Key` must be `CopyConstructible` only if the dereferenced `InputIterator` returns an lvalue or const rvalue.

(And similarly for multi.)

This was reworded to N2284 23.3.1.1 [map.cons]/3 and N2284 23.3.3.1 [set.cons]/4, and it slightly changed over the years into N3936 23.4.4.2 [map.cons]/3 and N3936 23.4.6.2 [set.cons]/4.

In 2005/2007, this was the best known way to say "hey, we should try to move this stuff", as the fine-grained element requirements were taking shape.

Then in 2010, N3173 was voted into WP N3225, adding the definition of `EmplaceConstructible` and modifying the container requirements tables to make the range constructors require `EmplaceConstructible`.

After looking at this history and double-checking our implementation (where `map`/`set` range construction goes through emplacement, with absolutely no special-casing for `map`'s pairs), I am convinced that N3173 superseded N1858 here. (Range-`insert()` and the unordered containers are unaffected.)

Previous resolution [SUPERSEDED]:

> This wording is relative to the N3936.

> Change 23.4.6.2 [set.cons] p4 as follows:

> >     template <class InputIterator>
> >       set(InputIterator first, InputIterator last,
> >         const Compare& comp = Compare(), const Allocator& = Allocator());

> > > -3- Effects: Constructs an empty `set` using the specified comparison object and allocator, and inserts elements from the range [`first,last`).

> > > -4- Requires: If the iterator's indirection operator returns an lvalue or a non-const rvalue, then `Key` shall be `CopyInsertible` into `*this`.

> > > -5- Complexity: Linear in `N` if the range [`first,last`) is already sorted using `comp` and otherwise `N logN`, where `N` is `last - first`.

Proposed resolution:

This wording is relative to the N3936.

1. Remove 23.4.4.2 [map.cons] p3:

   >     template <class InputIterator>
   >       map(InputIterator first, InputIterator last,
   >           const Compare& comp = Compare(), const Allocator& = Allocator());

   > > -3- Requires: If the iterator's indirection operator returns an lvalue or a `const` rvalue `pair<key_type, mapped_type>`, then both `key_type` and `mapped_type` shall be `CopyInsertible` into `*this`.

   > > […]

2. Remove 23.4.5.2 [multimap.cons] p3:

   >     template <class InputIterator>
   >       multimap(InputIterator first, InputIterator last,
   >                const Compare& comp = Compare(),
   >                const Allocator& = Allocator());

   > > -3- Requires: If the iterator's indirection operator returns an lvalue or a `const` rvalue `pair<key_type, mapped_type>`, then both `key_type` and `mapped_type` shall be `CopyInsertible` into `*this`.

   > > […]

3. Remove 23.4.6.2 [set.cons] p4:

   >     template <class InputIterator>
   >       set(InputIterator first, InputIterator last,
   >           const Compare& comp = Compare(), const Allocator& = Allocator());

   > > […]

   > > -4- Requires: If the iterator's indirection operator returns an lvalue or a non-`const` rvalue, then `Key` shall be `CopyInsertible` into `*this`.

4. Remove 23.4.7.2 [multiset.cons] p3:

   >     template <class InputIterator>
   >       multiset(InputIterator first, InputIterator last,
   >                const Compare& comp = Compare(),
   >                const Allocator& = Allocator());

   > > -3- Requires: If the iterator's indirection operator returns an lvalue or a `const` rvalue, then `Key` shall be `CopyInsertible` into `*this`.

   > > […]

### 2077. Further incomplete constraints for type traits

Section: 20.10.4.3 [meta.unary.prop] Status: Open Submitter: Daniel Krügler Opened: 2011-08-20 Last modified: 2014-02-11

View other active issues in [meta.unary.prop].

View all other issues in [meta.unary.prop].

View all issues with Open status.

Discussion:

The currently agreed on proposed wording for 2015 using `remove_all_extents<T>::type` instead of the "an array of unknown bound" terminology in the precondition should be extended to some further entries especially in Table 49, notably the `is_*constructible`, `is_*assignable`, and `is_*destructible` entries. To prevent ODR violations, incomplete element types of arrays must be excluded for value-initialization and destruction for example. Construction and assignment has to be honored, when we have array-to-pointer conversions or pointer conversions of incomplete pointees in effect.

[2012, Kona]

The issue is that in three type traits, we are accidentally saying that in certain circumstances the type must give a specified answer when given an incomplete type. (Specifically: an array of unknown bound of incomplete type.) The issue asserts that there's an ODR violation, since the trait returns false in that case but might return a different version when the trait is completed.

Howard argues: no, there is no risk of an ODR violation. `is_constructible<A[]>` must return `false` regardless of whether `A` is complete, so there's no reason to forbid an array of unknown bound of incomplete types. Same argument applies to `is_assignable`. General agreement with Howard's reasoning.

There may be a real issue for `is_destructible`. None of us are sure what `is_destructible` is supposed to mean for an array of unknown bound (regardless of whether its type is complete), and the standard doesn't make it clear. The middle column doesn't say what it's supposed to do for incomplete types.

In at least one implementation, `is_destructible<A[]>` does return `true` if `A` is complete, which would result in ODR violation unless we forbid it for incomplete types.

Move to open. We believe there is no issue for `is_constructible` or `is_assignable`, but that there is a real issue for `is_destructible`.

Proposed resolution:

### 2079. Required `pow()` overloads

Section: 26.8 [c.math] Status: New Submitter: Steve Clamage Opened: 2011-08-29 Last modified: 2014-02-11

View other active issues in [c.math].

View all other issues in [c.math].

View all issues with New status.

Discussion:

LWG issue 550 removed the functions:

>     float       pow(float, int);
>     double      pow(double, int);
>     long double pow(long double, int);

from header `<cmath>`. This change does not seem to be mentioned in Annex C, C.2.14.

Howard:

> N3290 26.8 [c.math]/p11 says:

> > Moreover, there shall be additional overloads sufficient to ensure:

> > 1. If any argument corresponding to a `double` parameter has type `long double`, then all arguments corresponding to `double` parameters are effectively cast to `long double`.
> > 2. Otherwise, if any argument corresponding to a `double` parameter has type `double` or an integer type, then all arguments corresponding to `double` parameters are effectively cast to `double`.
> > 3. Otherwise, all arguments corresponding to `double` parameters are effectively cast to `float`.

> From C99 7.12.7.4 we have:

> >     double pow(double, double);

> 26.8 [c.math]/p11/b2 says that if the client calls `pow(2.0f, 2)`, then the `int` for second argument causes the following effective call to be made:

> >     pow(static_cast<double>(2.0f), static_cast<double>(2)) -> double

> The first sentence of p11 implies that this is done by supplying the following additional overload:

> >     double pow(float, int);

> If the client calls `pow(2.0, 2)`, then the same reasoning (b2 again) implies the following additional overload:

> >     double pow(double, int);

> If the client calls `pow(2.0l, 2)`, then b1 implies the following additional overload:

> >     long double pow(long double, int);

> In all, p11 implies hundreds (perhaps thousands?) of extra overloads. All but one of which is a superset of the overloads required by C++98/03 (that one being `pow(float, int)` which had its return type changed from `float` to `double`).

> In practice, at least some vendors implement p11 by using templated overloads as opposed to ordinary overloads.

Steve Clamage:

> Thanks. I didn't see that those extra overloads were actually implied by p11, despite the first sentence. Without examples, the point is a bit subtle (at least for me).

Proposed resolution:

### 2088. `std::terminate` problem

Section: 18.8.3 [exception.terminate] Status: Open Submitter: Daniel Krügler Opened: 2011-09-25 Last modified: 2014-02-11

View all issues with Open status.

Discussion:

Andrzej Krzemienski reported the following on comp.std.c++:

> In N3290, which is to become the official standard, in 18.8.3.4 [terminate], paragraph 1 reads

> > Remarks: Called by the implementation when exception handling must be abandoned for any of several reasons (15.5.1), in effect immediately after evaluating the throw-expression (18.8.3.1). May also be called directly by the program.

> It is not clear what is "in effect". It was clear in previous drafts where paragraphs 1 and 2 read:

> > Called by the implementation when exception handling must be abandoned for any of several reasons (15.5.1). May also be called directly by the program.

> > Effects: Calls the `terminate_handler` function in effect immediately after evaluating the throw-expression (18.8.3.1), if called by the implementation, or calls the current `terminate_handler` function, if called by the program.

> It was changed by N3189. The same applies to function unexpected (D. 11.4, paragraph 1).

> Assuming the previous wording is still intended, the wording can be read "unless `std::terminate` is called by the program, we will use the handler that was in effect immediately after evaluating the throw-expression".

> This assumes that there is some throw-expression connected to every situation that triggers the call to `std::terminate`. But this is not the case:
> - In case `std::thread` is assigned to or destroyed while being joinable there is no throw-expression involved.
> - In case `std::unexpected` is called by the program, `std::terminate` is triggered by the implementation - no throw-expression involved.
> - In case a destructor throws during stack unwinding we have two throw-expressions involved.

> Which one is referred to?

> In case `std::nested_exception::rethrow_nested` is called for an object that has captured no exception, there is no throw-expression involved directly (and may no throw be involved even indirectly).

> Next, 18.8.3.1 [terminate.handler], paragraph 2 says

> > Required behavior: A `terminate_handler` shall terminate execution of the program without returning to the caller.

> This seems to allow that the function may exit by throwing an exception (because word "return" implies a normal return).

> One could argue that words "terminate execution of the program" are sufficient, but then why "without returning to the caller" would be mentioned. In case such handler throws, noexcept specification in function `std::terminate` is violated, and `std::terminate` would be called recursively - should `std::abort` not be called in case of recursive `std::terminate` call? On the other hand some controlled recursion could be useful, like in the following technique.

The here mentioned wording changes by N3189 in regard to 18.8.3.4 [terminate] p1 were done for a better separation of effects (Effects element) and additional normative wording explanations (Remarks element), there was no meaning change intended. Further, there was already a defect existing in the previous wording, which was not updated when further situations where defined, when `std::terminate` where supposed to be called by the implementation.

The part

"in effect immediately after evaluating the throw-expression"

should be removed and the quoted reference to 18.8.3.1 [terminate.handler] need to be part of the effects element where it refers to the current `terminate_handler` function, so should be moved just after

"Effects: Calls the current `terminate_handler` function."

It seems ok to allow a termination handler to exit via an exception, but the suggested idiom should better be replaced by a more simpler one based on evaluating the current exception pointer in the terminate handler, e.g.

>     void our_terminate (void) {
>       std::exception_ptr p = std::current_exception();
>       if (p) {
>         ... // OK to rethrow and to determine it's nature
>       } else {
>         ... // Do something else
>       }
>     }

[2011-12-09: Daniel comments]

A related issue is 2111.

[2012, Kona]

Move to Open.

There is an interaction with Core issues in this area that Jens is already supplying wording for. Review this issue again once Jens wording is available.

Alisdair to review clause 15.5 (per Jens suggestion) and recommend any changes, then integrate Jens wording into this issue.

Proposed resolution:

### 2089. `std::allocator::construct` should use uniform initialization

Section: 20.7.9.1 [allocator.members] Status: Open Submitter: David Krauss Opened: 2011-10-07 Last modified: 2014-02-11

View all other issues in [allocator.members].

View all issues with Open status.

Discussion:

When the `EmplaceConstructible` (23.2.1 [container.requirements.general]/13) requirement is used to initialize an object, direct-initialization occurs. Initializing an aggregate or using a `std::initializer_list` constructor with emplace requires naming the initialized type and moving a temporary. This is a result of `std::allocator::construct` using direct-initialization, not list-initialization (sometimes called "uniform initialization") syntax.

Altering `std::allocator<T>::construct` to use list-initialization would, among other things, give preference to `std::initializer_list` constructor overloads, breaking valid code in an unintuitive and unfixable way — there would be no way for `emplace_back` to access a constructor preempted by `std::initializer_list` without essentially reimplementing `push_back`.

>     std::vector<std::vector<int>> v;
>     v.emplace_back(3, 4); // v[0] == {4, 4, 4}, not {3, 4} as in list-initialization

The proposed compromise is to use SFINAE with `std::is_constructible`, which tests whether direct-initialization is well formed. If `is_constructible` is false, then an alternative `std::allocator::construct` overload is chosen which uses list-initialization. Since list-initialization always falls back on direct-initialization, the user will see diagnostic messages as if list-initialization (uniform-initialization) were always being used, because the direct-initialization overload cannot fail.

I can see two corner cases that expose gaps in this scheme. One occurs when arguments intended for `std::initializer_list` satisfy a constructor, such as trying to emplace-insert a value of `{3, 4}` in the above example. The workaround is to explicitly specify the `std::initializer_list` type, as in `v.emplace_back(std::initializer_list<int>(3, 4))`. Since this matches the semantics as if `std::initializer_list` were deduced, there seems to be no real problem here.

The other case is when arguments intended for aggregate initialization satisfy a constructor. Since aggregates cannot have user-defined constructors, this requires that the first nonstatic data member of the aggregate be implicitly convertible from the aggregate type, and that the initializer list have one element. The workaround is to supply an initializer for the second member. It remains impossible to in-place construct an aggregate with only one nonstatic data member by conversion from a type convertible to the aggregate's own type. This seems like an acceptably small hole.

The change is quite small because `EmplaceConstructible` is defined in terms of whatever allocator is specified, and there is no need to explicitly mention SFINAE in the normative text.

[2012, Kona]

Move to Open.

There appears to be a real concern with initializing aggregates, that can be performed only using brace-initialization. There is little interest in the rest of the issue, given the existence of 'emplace' methods in C++11.

Move to Open, to find an acceptable solution for intializing aggregates. There is the potential that EWG may have an interest in this area of language consistency as well.

[2013-10-13, Ville]

This issue is related to 2070.

Proposed resolution:

This wording is relative to the FDIS.

Change 20.7.9.1 [allocator.members] p12 as indicated:

>     template <class U, class... Args>
>       void construct(U* p, Args&&... args);

> > 12 Effects: `::new((void *)p) U(std::forward<Args>(args)...)` if `is_constructible<U, Args...>::value` is `true`, else `::new((void *)p) U{std::forward<Args>(args)...}`

### 2095. `promise` and `packaged_task` missing constructors needed for uses-allocator construction

Section: 30.6.5 [futures.promise], 30.6.9 [futures.task] Status: Open Submitter: Jonathan Wakely Opened: 2011-11-01 Last modified: 2014-06-17

View other active issues in [futures.promise].

View all other issues in [futures.promise].

View all issues with Open status.

Discussion:

This example is ill-formed according to C++11 because `uses_allocator<promise<R>, A>::value` is true, but `is_constructible<promise<R>, A, promise<R>&&>::value` is false. Similarly for `packaged_task`.

>     #include <future>
>     #include <memory>
>     #include <tuple>

>     using namespace std;

>     typedef packaged_task<void()> task;
>     typedef promise<void> prom;
>     allocator<task> a;

>     tuple<task, prom> t1{ allocator_arg, a };
>     tuple<task, prom> t2{ allocator_arg, a, task{}, prom{} };

[2012, Portland]

This is an allocator issue, and should be dealt with directly by LWG.

[2013-03-06]

Jonathan suggests to make the new constructors non-explicit and makes some representational improvements.

[2013-09 Chicago]

Move to deferred.

This issue has much in common with similar problems with `std::function` that are being addressed by the polymorphic allocators proposal currently under evaluation in LEWG. Defer further discussion on this topic until the final outcome of that paper and its proposed resolution is known.

[2014-02-20 Re-open Deferred issues as Priority 4]

Proposed resolution:

[This wording is relative to the FDIS.]

1. Add to 30.6.5 [futures.promise], class template `promise` synopsis, as indicated:

   >     namespace std {
   >       template <class R>
   >       class promise {
   >       public:
   >         promise();
   >         template <class Allocator>
   >         promise(allocator_arg_t, const Allocator& a);
   >         template <class Allocator>
   >         promise(allocator_arg_t, const Allocator& a, promise&& rhs) noexcept;
   >         promise(promise&& rhs) noexcept;
   >         promise(const promise& rhs) = delete;
   >         ~promise();
   >         […]
   >       };
   >       […]
   >     }

2. Change 30.6.5 [futures.promise] as indicated:

   >     promise(promise&& rhs) noexcept;
   >     template <class Allocator>
   >     promise(allocator_arg_t, const Allocator& a, promise&& rhs) noexcept;

   > > -5- Effects: constructs a new `promise` object and transfers ownership of the shared state of `rhs` (if any) to the newly-constructed object.

   > > -6- Postcondition: `rhs` has no shared state.

   > > -?- [Note: `a` is not used — end note]

3. Add to 30.6.9 [futures.task], class template `packaged_task` synopsis, as indicated:

   >     namespace std {
   >       template<class> class packaged_task; // undefined

   >       template<class R, class... ArgTypes>
   >       class packaged_task<R(ArgTypes...)> {
   >       public:
   >         // construction and destruction
   >         packaged_task() noexcept;
   >         template <class Allocator>
   >           packaged_task(allocator_arg_t, const Allocator& a) noexcept;
   >         template <class F>
   >           explicit packaged_task(F&& f);
   >         template <class F, class Allocator>
   >           explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f);
   >         ~packaged_task();

   >         // no copy
   >         packaged_task(const packaged_task&) = delete;
   >         template<class Allocator>
   >           packaged_task(allocator_arg_t, const Allocator& a, const packaged_task&) = delete;
   >         packaged_task& operator=(const packaged_task&) = delete;

   >         // move support
   >         packaged_task(packaged_task&& rhs) noexcept;
   >         template <class Allocator>
   >           packaged_task(allocator_arg_t, const Allocator& a, packaged_task&& rhs) noexcept;
   >         packaged_task& operator=(packaged_task&& rhs) noexcept;
   >         void swap(packaged_task& other) noexcept;
   >         […]
   >       };
   >       […]
   >     }

4. Change 30.6.9.1 [futures.task.members] as indicated:

   >     packaged_task() noexcept;
   >     template <class Allocator>
   >       packaged_task(allocator_arg_t, const Allocator& a) noexcept;

   > > -1- Effects: constructs a `packaged_task` object with no shared state and no stored task.

   > > -?- [Note: `a` is not used — end note]

   […]

   >     packaged_task(packaged_task&& rhs) noexcept;
   >     template <class Allocator>
   >       packaged_task(allocator_arg_t, const Allocator& a, packaged_task&& rhs) noexcept;

   > > -5- Effects: constructs a new `packaged_task` object and transfers ownership of `rhs`'s shared state to `*this`, leaving `rhs` with no shared state. Moves the stored task from `rhs` to `*this`.

   > > -6- Postcondition: `rhs` has no shared state.

   > > -?- [Note: `a` is not used — end note]

### 2101. Some transformation types can produce impossible types

Section: 20.10.7 [meta.trans] Status: Open Submitter: Daniel Krügler Opened: 2011-11-18 Last modified: 2014-05-23

View all issues with Open status.

Discussion:

Table 53 — "Reference modifications" says in regard to the type trait `add_lvalue_reference` (emphasize mine)

> If `T` names an object or function type then the member typedef type shall name `T&`;

The problem with this specification is that function types with cv-qualifier or ref-qualifier, like

>     void() const
>     void() &

are also affected by the first part of the rule, but this would essentially mean, that instantiating `add_lvalue_reference` with such a type would attempt to form a type that is not defined in the C++ type system, namely

>     void(&)() const
>     void(&)() &

The general policy for TransformationTraits is to define always some meaningful mapping type, but this does not hold for `add_lvalue_reference`, `add_rvalue_reference`, and in addition to these two for `add_pointer` as well. The latter one would attempt to form the invalid types

>     void(*)() const
>     void(*)() &

A possible reason why those traits were specified in this way is that in C++03 (and that means for TR1), cv-qualifier were underspecified in the core language and several compilers just ignored them during template instantiations. This situation became fixed by adopting CWG issues 295 and 547.

While there is possibly some core language clarification needed (see reflector messages starting from c++std-core-20740), it seems also clear that the library should fix the specification. The suggested resolution follows the style of the specification of the support concepts `PointeeType` and `ReferentType` defined in N2914.

[2012-02-10, Kona]

Move to NAD.

These cv- and ref-qualified function types are aberrations in the type system, and do not represent any actual entity defined by the language. The notion of cv- and ref- qualification applies only to the implicit `*this` reference in a member function.

However, these types can be produced by quirks of template metaprogramming, the question remains what the library should do about it. For example, `add_reference` returns the original type if passed a reference type, or a `void` type. Conversely, `add_pointer` will return a pointer to the referenced type when passed a reference.

It is most likely that the 'right' answer in any case will depend on the context that the question is being asked, in terms of forming these obscure types. The best the LWG can do is allow an error to propagate back to the user, so they can provide their own meaningful answer in their context - with additional metaprogramming on their part. The consensus is that if anyone is dangerous enough with templates to get themselves into this problem, they will also have the skills to resolve the problem themselves. This is not going to trip up the non-expert developer.

Lastly, it was noted that this problem arises only because the language is inconsistent in providing us these nonsense types that do no really represent anything in the language. There may be some way Core or Evolution could give us a more consistent type system so that the LWG does not need to invent an answer at all, should this question need resolving. This is another reason to not specify anything at the LWG trait level at this time, leaving the other working groups free to produce the 'right' answer that we can then follow without changing the meaning of existing, well-defined programs.

[2012-02-10, post-Kona]

Move back to Open. Daniel is concerned that this is not an issue we can simply ignore, further details to follow.

[2012-10-06, Daniel comments]

This issue really should be resolved as a defect: First, the argument that "forming these obscure types" should "allow an error to propagate" is inconsistent with the exact same "obscure type" that would be formed when `std::add_lvalue_reference<void>` wouldn't have an extra rules for `void` types, which also cannot form references. The originally proposed resolution attempts to apply the same solution for the same common property of `void` types and function types with cv-qualifiers or ref-qualifier. These functions had the property of `ReferentType` during concept time (see CWG 749 bullet three for the final wording).

Core issue CWG 1417 has clarified that any attempt to form a reference of a pointer to a function type with cv-qualifiers or ref-qualifier is ill-formed. Unfortunately, many compilers don't implement this yet.

I also would like to warn about so-called "obscure" types: The problem is that these can occur as the side effect of finding a best match overload of function templates, where this type is exactly correct for one of these overloads, but causes a deep (not-sfinae-friendly) error for others where one of these traits are part of the signature.

Existing experience with `void` types shows, that this extra rule is not so unexpected. Further, any usage of the result types of these traits as argument types or return types of functions would make these ill-formed (and in a template context would be sfinaed away), so the expected effects are rarely unnoticed. Checking all existing explicit usages of the traits `add_rvalue_reference`, `add_lvalue_reference`, and `add_pointer` didn't show any example where the error would be silent: `add_rvalue_reference` is used to specify the return value of `declval()` and the instantiation of `declval<void() const>()` would be invalid, because of the attempt to return a function type. Similarly, `add_lvalue_reference` is used to specify the return type of `unique_ptr<T>::operator*()`. Again, any instantiation with `void() const` wouldn't remain unnoticed. The trait `add_pointer` is used to specify the trait `std::decay` and this is an interesting example, because it is well-formed when instantiated with `void` types, too, and is heavily used throughout the library specification. All use-cases would not be negatively affected by the suggested acceptance of function types with cv-qualifiers or ref-qualifier, because they involve types that are either function arguments, function parameters or types were references are formed from.

The alternative would be to add an additional extra rule that doesn't define a type member 'type' when we have a function type with cv-qualifiers or ref-qualifier. This is better than the current state but it is not superior than the proposal to specify the result as the original type, because both variants are sfinae-friendly. A further disadvantage of the "non-type" approach here would be that any usage of `std::decay` would require special protection against these function types, because instantiating `std::decay<void() const>` again would lead to a deep, sfinae-unfriendly error.

The following example demonstrates the problem: Even though the second `f` template is the best final match here, the first one will be instantiated. During that process `std::decay<T>::type` becomes instantiated as well and will raise a deep error, because as part of the implementation the trait `std::add_pointer<void() const>` becomes instantiated:

>     #include <type_traits>

>     template<class T>
>     typename std::decay<T>::type f(T&& t);

>     template<class T, class U>
>     U f(U u);

>     int main() {
>       f<void() const>(0);
>     }

When the here proposed resolution would be applied this program would be well-formed and selects the expected function.

Previous resolution from Daniel [SUPERSEDED]:

> 1. Change Table 53 — "Reference modifications" in 20.10.7.2 [meta.trans.ref] as indicated:

>    Table 53 — Reference modifications
>    Template | Comments
>    --- | ---
>    `…`
>    `template <class T> struct add_lvalue_reference;` | If `T` names an object `type` or if `T` names a function type that does not have cv-qualifiers or a ref-qualifier then the member typedef `type` shall name `T&`; otherwise, if `T` names a type "rvalue reference to `T1`" then the member typedef `type` shall name `T1&`; otherwise, `type` shall name `T`.
>    `template <class T> struct add_rvalue_reference;` | If `T` names an object `type` or if `T` names a function type that does not have cv-qualifiers or a ref-qualifier then the member typedef `type` shall name `T&&`; otherwise, `type` shall name `T`. [Note: This rule reflects the semantics of reference collapsing (8.3.2 [dcl.ref]). For example, when a type `T` names a type `T1&`, the type `add_rvalue_reference<T>::type` is not an rvalue reference. — end note]

> 2. Change Table 56 — "Pointer modifications" in 20.10.7.5 [meta.trans.ptr] as indicated:

>    Table 56 — Pointer modifications
>    Template | Comments
>    --- | ---
>    `…`
>    `template <class T> struct add_pointer;` | The member typedef `type` shall name the same type as If `T` names a function type that has cv-qualifiers or a ref-qualifier then the member typedef `type` shall name `T`; otherwise, it shall name the same type as `remove_reference<T>::type*`.

The following revised proposed resolution defines - in the absence of a proper core language definition - a new term referenceable type as also suggested by the resolution for LWG 2196 as an umbrella of the negation of `void` types and function types with cv-qualifiers or ref-qualifier. This simplifies and minimizes the requires wording changes.

[ 2013-09-26, Daniel synchronizes wording with recent draft ]

[ 2014-05-18, Daniel synchronizes wording with recent draft and comments ]

My impression is that this urgency of action this issue attempts to point out is partly caused by the fact that even for the most recent C++14 compilers the implementations have just recently changed to adopt the core wording. Examples for these are bug reports to gcc or clang.

Occasionally the argument has been presented to me that the suggested changes to the traits affected by this issue would lead to irregularities compared to other traits, especially the lack of guarantee that `add_pointer` might not return a pointer or that `add_(l/r)value_reference` might not return a reference type. I would like to point out that this kind of divergence is actually already present in most `add/remove` traits: For example, we have no guarantee that `add_const` returns a const type (Reference types or function types get special treatments), or that `add_rvalue_reference` returns an rvalue-reference (e.g. when applied to an lvalue-reference type).

Zhihao Yuan brought to my attention, that the originally proposing paper N1345 carefully discussed these design choices.

Proposed resolution:

This wording is relative to N3936.

1. Change Table 53 — "Reference modifications" in 20.10.7.2 [meta.trans.ref] as indicated:

   Table 53 — Reference modifications
   Template | Comments
   --- | ---
   `…`
   `template <class T> struct add_lvalue_reference;` | If `T` names an object or function type a referenceable type then the member typedef `type` shall name `T&`; otherwise, if `T` names a type "rvalue reference to `T1`" then the member typedef `type` shall name `T1&`; otherwise, `type` shall name `T`. [Note: This rule reflects the semantics of reference collapsing (8.3.2 [dcl.ref]). — end note]
   `template <class T> struct add_rvalue_reference;` | If `T` names an object or function type a referenceable type then the member typedef `type` shall name `T&&`; otherwise, `type` shall name `T`. [Note: This rule reflects the semantics of reference collapsing (8.3.2 [dcl.ref]). For example, when a type `T` names a type `T1&`, the type `add_rvalue_reference_t<T>` is not an rvalue reference. — end note]

2. Change Table 56 — "Pointer modifications" in 20.10.7.5 [meta.trans.ptr] as indicated:

   Table 56 — Pointer modifications
   Template | Comments
   --- | ---
   `…`
   `template <class T> struct add_pointer;` | If `T` names a referenceable type or a (possibly cv-qualified) `void` type then T the member typedef `type` shall name the same type as `remove_reference_t<T>*`; otherwise, `type` shall name `T`.

### 2106. `move_iterator` wrapping iterators returning prvalues

Section: 24.5.3 [move.iterators] Status: Tentatively Ready Submitter: Dave Abrahams Opened: 2011-11-30 Last modified: 2014-05-23

View all other issues in [move.iterators].

View all issues with Tentatively Ready status.

Discussion:

Shouldn't `move_iterator` be specialized so that if the iterator it wraps returns a prvalue when dereferenced, the `move_iterator` also returns by value? Otherwise, it creates a dangling reference.

Howard: I believe just changing `move_iterator<I>::reference` would do. A direction might be testing on `is_reference<iterator_traits<I>::reference>`, or `is_reference<decltype(*declval<I>())>`.

Daniel: I would prefer to use a consistent style among the iterator adaptors, so I suggest to keep with the `iterator_traits` typedefs if possible.

>     using reference = typename conditional<
>       is_reference<typename iterator_traits<Iterator>::reference>::value,
>       value_type&&,
>       value_type
>     >::type;

We might also want to ensure that if `Iterator`'s `reference` type is a reference, the referent is equal to `value_type` (after removal of cv-qualifiers). In general we have no such guarantee.

Marc: In the default case where we don't return `value_type&&`, should we use `value_type` or should we keep the `reference` type of the wrapped iterator?

Daniel: This suggestion looks appealing at first, but the problem here is that using this typedef can make it impossible for `move_iterator` to satisfy its contract, which means returning an rvalue of the value type (Currently it says rvalue-reference, but this must be fixed as of this issue anyway). I think that user-code can reasonably expect that when it has constructed an object `m` of `move_iterator<It>`, where `It` is a valid mutable iterator type, the expression

>     It::value_type&& rv = *m;

is well-formed.

Let's set `R` equal to `iterator_traits<Iterator>::reference` in the following. We can discuss the following situations:

1. `R` is a reference type: We can only return the corresponding xvalue of `R`, if `value_type` is reference-related to the referent type, else this is presumably no forward iterator and we cannot say much about it, except that it must be convertible to `value_type`, so it better should return a prvalue.
2. `R` is not a reference type: In this case we can rely on a conversion to `value_type` again, but not much more. Assume we would return `R` directly, this might turn out to have a conversion to an lvalue-reference type of the value type (for example). If that is the case, this would indirectly violate the contract of `move_iterator`.

In regard to the first scenario I suggest that implementations are simply required to check that `V2 = remove_cv<remove_reference<R>::type>::type` is equal to the value type `V1` as a criterion to return this reference as an xvalue, in all other cases it should return the value type directly as prvalue.

The additional advantage of this strategy is, that we always ensure that `reference` has the correct cv-qualification, if `R` is a real reference.

It is possible to improve this a bit by indeed supporting reference-related types, this would require to test `is_same<V1, V2>::value || is_base_of<V1, V2>::value` instead. I'm unsure whether (a) this additional effort is worth it and (b) a strict reading of the forward iterator requirements seems not to allow to return a reference-related type (Whether this is a defect or not is another question).

[2011-12-05: Marc Glisse comments and splits into two resolution alternatives]

I guess I am looking at the speed of:

>     value_type x;
>     x = *m;

(copy construction would likely trigger copy elision and thus be neutral) instead of the validity of:

>     value_type&& x = *m;

In this sense, Daniels earlier proposition that ignored `value_type` and just did `switch_lvalue_ref_to_rvalue_ref<reference>` was easier to understand (and it didn't require thinking about reference related types).

The currently proposed resolution has been split into two alternatives.

[2012, Kona]

Move to Review.

Alisdair: This only applies to input iterators, so keep that in mind when thinking about this.

STL: I see what B is doing, but not A.

Howard: I agree.

Alisdair: Should we use `add_rvalue_reference`?

STL: No, we do not want reference collapsing.

STL: Re A, messing with the CV qualification scares me.

Alisdair: Agree. That would break my intent.

STL: Actually I don't think it's actually wrong, but I still don't see what it's doing.

Alisdair: A is picking the value type, B is picking the proxy type.

Howard: I like returning the proxy type.

STL: Returning a reference (B) seems right, because the requirements say "reference". I suspect that B works correctly if you have a move iterator wrapping a move iterator wrapping a thing. I think that A would mess up the type in the middle.

Considerable discussion about which version is correct, checking various examples.

STL: Still think B is right. Still don't understand A. In A we are losing the proxyness.

Howard: Agree 100%. We don't want to lose the proxy. If it's const, so be it.

STL: B is also understandable by mortals.

Howard: Remove to review, keep A but move it out of the proposed resolution area (but keep it for rational).

Alisdair: Adding an explanatory note might be a good idea, if someone wants to write one.

Walter: Concerned about losing the word "reference" in p.1.

Howard: `move_iterator` will return an xvalue or a prvalue, both of which are rvalues.

[Proposed resolution A, rejected in preference to the currently proposed resolution (B)

1. Change 24.5.3 [move.iterators] p1 as indicated:

   > Class template `move_iterator` is an iterator adaptor with the same behavior as the underlying iterator except that its dereference operator implicitly converts the value returned by the underlying iterator's dereference operator to an rvalue reference of the value type. Some generic algorithms can be called with move iterators to replace copying with moving.

2. Change 24.5.3.1 [move.iterator], class template `move_iterator` synopsis, as indicated:

   >     namespace std {
   >       template <class Iterator>
   >       class move_iterator {
   >       public:
   >         typedef Iterator iterator_type;
   >         typedef typename iterator_traits<Iterator>::difference_type difference_type;
   >         typedef Iterator pointer;
   >         typedef typename iterator_traits<Iterator>::value_type value_type;
   >         typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
   >         typedef value_type&&see below reference;
   >         […]
   >       };
   >     }

3. Immediately following the class template `move_iterator` synopsis in 24.5.3.1 [move.iterator] insert a new paragraph as indicated:

   > -?- Let `R` be `iterator_traits<Iterator>::reference` and let `V` be `iterator_traits<Iterator>::value_type`. If `is_reference<R>::value` is `true` and if `remove_cv<remove_reference<R>::type>::type` is the same type as `V`, the template instantiation `move_iterator<Iterator>` shall define the nested type named `reference` as a synonym for `remove_reference<R>::type&&`, otherwise as a synonym for `V`.

]

[2012, Portland: Move to Tentatively Ready]

AJM wonders if the implied trait might be useful elsewhere, and worth adding to type traits as a transformation type trait.

Suspicion that the Range SG might find such a trait useful, but wait until there is clear additional use of such a trait before standardizing.

Minor wording tweak to use `add_rvalue_reference` rather than manually adding the `&&`, then move to Tentatively Ready.

[2013-01-09 Howard Hinnant comments]

I believe the P/R for LWG 2106 is incorrect (item 3). The way it currently reads, `move_iterator<I>::reference` is always an lvalue reference. I.e. if `R` is an lvalue reference type, then reference becomes `add_rvalue_reference<R>::type` which is just `R`. And if `R` is not a reference type, then reference becomes `R` (which is also just `R` ;-)).

I believe the correct wording is what was there previously:

-?- Let `R` be `iterator_traits<Iterator>::reference`. If `is_reference<R>::value` is true, the template instantiation `move_iterator<Iterator>` shall define the nested type named `reference` as a synonym for `remove_reference<R>::type&&`, otherwise as a synonym for `R`.

Additionally Marc Glisse points out that `move_iterator<I>::operator*()` should return `static_cast<reference>(*current)`, not `std::move(*current)`.

Previous resolution:

> This wording is relative to the FDIS.

> 1. Change 24.5.3 [move.iterators] p1 as indicated:

>    > Class template `move_iterator` is an iterator adaptor with the same behavior as the underlying iterator except that its dereference operator implicitly converts the value returned by the underlying iterator's dereference operator to an rvalue reference. Some generic algorithms can be called with move iterators to replace copying with moving.

> 2. Change 24.5.3.1 [move.iterator], class template `move_iterator` synopsis, as indicated:

>    >     namespace std {
>    >       template <class Iterator>
>    >       class move_iterator {
>    >       public:
>    >         typedef Iterator iterator_type;
>    >         typedef typename iterator_traits<Iterator>::difference_type difference_type;
>    >         typedef Iterator pointer;
>    >         typedef typename iterator_traits<Iterator>::value_type value_type;
>    >         typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
>    >         typedef value_type&&see below reference;
>    >         […]
>    >       };
>    >     }

> 3. Immediately following the class template `move_iterator` synopsis in 24.5.3.1 [move.iterator] insert a new paragraph as indicated:

>    > -?- Let `R` be `iterator_traits<Iterator>::reference`. If `is_reference<R>::value` is `true`, the template instantiation `move_iterator<Iterator>` shall define the nested type named `reference` as a synonym for `add_rvalue_reference<R>::type`, otherwise as a synonym for `R`.

[2014-05-19, Daniel comments]

The term instantiation has been changed to specialization in the newly added paragraph as suggested by STL and much preferred by myself.

[2014-05-19 Library reflector vote]

The issue has been identified as Tentatively Ready based on five votes in favour.

Proposed resolution:

This wording is relative to N3936.

1. Change 24.5.3 [move.iterators] p1 as indicated:

   > Class template `move_iterator` is an iterator adaptor with the same behavior as the underlying iterator except that its indirection operator implicitly converts the value returned by the underlying iterator's indirection operator to an rvalue reference. Some generic algorithms can be called with move iterators to replace copying with moving.

2. Change 24.5.3.1 [move.iterator], class template `move_iterator` synopsis, as indicated:

   >     namespace std {
   >       template <class Iterator>
   >       class move_iterator {
   >       public:
   >         typedef Iterator iterator_type;
   >         typedef typename iterator_traits<Iterator>::difference_type difference_type;
   >         typedef Iterator pointer;
   >         typedef typename iterator_traits<Iterator>::value_type value_type;
   >         typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
   >         typedef value_type&&see below reference;
   >         […]
   >       };
   >     }

3. Immediately following the class template `move_iterator` synopsis in 24.5.3.1 [move.iterator] insert a new paragraph as indicated:

   > -?- Let `R` be `iterator_traits<Iterator>::reference`. If `is_reference<R>::value` is `true`, the template specialization `move_iterator<Iterator>` shall define the nested type named `reference` as a synonym for `remove_reference<R>::type&&`, otherwise as a synonym for `R`.

4. Edit 24.5.3.3.4 [move.iter.op.star] p1 as indicated:

   >     reference operator*() const;

   > > -1- Returns: `std::movestatic_cast<reference>(*current)`.

### 2108. No way to identify allocator types that always compare equal

Section: 17.6.3.5 [allocator.requirements] Status: Open Submitter: Jonathan Wakely Opened: 2011-12-01 Last modified: 2014-02-11

View other active issues in [allocator.requirements].

View all other issues in [allocator.requirements].

View all issues with Open status.

Discussion:

Whether two allocator objects compare equal affects the complexity of container copy and move assignments and also the possibility of an exception being thrown by container move assignments. The latter point means container move assignment cannot be `noexcept` when `propagate_on_container_move_assignment` (POCMA) is false for the allocator because there is no way to detect at compile-time if two allocators will compare equal. LWG 2013 means this affects all containers using `std::allocator`, but even if that is resolved, this affects all stateless allocators which do not explicitly define POCMA to `true_type`.

One solution would be to add an "always_compare_equal" trait to `allocator_traits`, but that would be duplicating information that is already defined by the type's equality operator if that operator always returns true. Requiring users to write `operator==` that simply returns true and also explicitly override a trait to repeat the same information would be unfortunate and risk user errors that allow the trait and actual `operator==` to disagree.

Dave Abrahams suggested a better solution in message c++std-lib-31532, namely to allow `operator==` to return `true_type`, which is convertible to `bool` but also detectable at compile-time. Adopting this as the recommended way to identify allocator types that always compare equal only requires a slight relaxation of the allocator requirements so that `operator==` is not required to return `bool` exactly.

The allocator requirements do not make it clear that it is well-defined to compare non-const values, that should be corrected too.

In message c++std-lib-31615 Pablo Halpern suggested an `always_compare_equal` trait that could still be defined, but with a sensible default value rather than requiring users to override it, and using that to set sensible values for other allocator traits:

> Do we still need `always_compare_equal` if we can have an `operator==` that returns `true_type`? What would its default value be? `is_empty<A> || is_convertible<decltype(a == a), true_type>::value`, perhaps? One benefit I see to such a definition is that stateless C++03 allocators that don't use the `true_type` idiom will still benefit from the new trait.

> […]

> One point that I want to ensure doesn't get lost is that if we adopt some sort of `always_compare_equal`-like trait, then `propagate_on_container_swap` and `propagate_on_container_move_assignment` should default to `always_compare_equal`. Doing this will eliminate unnecessary requirements on the container element type, as per [LWG 2103].

Optionally, `operator==` for `std::allocator` could be made to return `true_type`, however if LWG 2103 is adopted that is less important.

Alberto Ganesh Barbati: Suggest either `always_compare_equal`, `all_objects_(are_)equivalent`, or `all_objects_compare_equal`.

Proposed resolution:

This wording is relative to the FDIS.

1. Change Table 27 — "Descriptive variable definitions" in 17.6.3.5 [allocator.requirements]:

   Table 27 — Descriptive variable definitions
   Variable | Definition
   --- | ---
   `a3, a4` | an rvalue of values of (possibly `const`) type `X`
   `b` | a value of (possibly `const`) type `Y`

2. Change Table 28 — "Allocator requirements" in 17.6.3.5 [allocator.requirements]:

   Table 28 — Allocator requirements
   Expression | Return type | Assertion/note pre-/post-condition | Default
   --- | --- | --- | ---
   `a1 == a2a3 == a4` | convertible to `bool` | returns true only if storage allocated from each can be deallocated via the other. `operator==` shall be reflexive, symmetric, and transitive, and shall not exit via an exception. |
   `a1 != a2a3 != a4` | convertible to `bool` | same as `!(a1 == a2)!(a3 == a4)` |
   `a3 == b` | convertible to `bool` | same as `a3 == Y::rebind<T>::other(b)` |
   `a3 != b` | convertible to `bool` | same as `!(a3 == b)` |
   `[…]`
   `a.select_on_- container_copy_- construction()` | `X` | Typically returns either `a` or `X()` | `return a;`
   `X::always_compares_equal` | Identical to or derived from `true_type` or `false_type` | `true_type` if the expression `x1 == x2` is guaranteed to be `true` for any two (possibly `const`) values `x1, x2` of type `X`, when implicitly converted to `bool`. See Note B, below. | `true_type`, if `is_empty<X>::value` is `true` or if `decltype(declval<const X&>() == declval<const X&>())` is convertible to `true_type`, otherwise `false_type`.
   `[…]`

   Note A: […]

   Note B: If `X::always_compares_equal::value` or `XX::always_compares_equal::value` evaluate to `true` and an expression equivalent to `x1 == x2` or `x1 != x2` for any two values `x1, x2` of type `X` evaluates to `false` or `true`, respectively, the behaviour is undefined.

3. Change class template `allocator_traits` synopsis, 20.7.8 [allocator.traits] as indicated:

   >     namespace std {
   >       template <class Alloc> struct allocator_traits {
   >         typedef Alloc allocator_type;
   >         […]
   >         typedef see below always_compares_equal;
   >         typedef see below propagate_on_container_copy_assignment;
   >         […]
   >       };
   >     }

4. Insert the following between 20.7.8.1 [allocator.traits.types] p6 and p7 as indicated:

   >     typedef see below always_compares_equal;

   > > -?- Type: `Alloc::always_compares_equal` if such a type exists; otherwise, `true_type` if `is_empty<Alloc>::value` is `true` or if `decltype(declval<const Alloc&>() == declval<const Alloc&>())` is convertible to `true_type`; otherwise, `false_type` .

   >     typedef see below propagate_on_container_copy_assignment;

   > > -7- Type: `Alloc::propagate_on_container_copy_assignment` if such a type exits, otherwise `false_type`.

5. Change class template `allocator` synopsis, 20.7.9 [default.allocator] as indicated:

   >     namespace std {
   >       template <class T> class allocator;

   >       // specialize for void:
   >       template <> class allocator<void> {
   >       public:
   >         typedef void* pointer;
   >         typedef const void* const_pointer;
   >         // reference-to-void members are impossible.
   >         typedef void value_type;
   >         template <class U> struct rebind { typedef allocator<U> other; };
   >       };

   >       template <class T> class allocator {
   >       public:
   >         typedef size_t size_type;
   >         typedef ptrdiff_t difference_type;
   >         typedef T* pointer;
   >         typedef const T* const_pointer;
   >         typedef T& reference;
   >         typedef const T& const_reference;
   >         typedef T value_type;
   >         template <class U> struct rebind { typedef allocator<U> other; };
   >         typedef true_type always_compares_equal;

   >         […]
   >       };
   >     }

### 2111. Which `unexpected`/`terminate` handler is called from the exception handling runtime?

Section: 18.8.3.4 [terminate], D.11.4 [unexpected] Status: Review Submitter: Howard Hinnant Opened: 2011-12-06 Last modified: 2014-03-02

View all other issues in [terminate].

View all issues with Review status.

Discussion:

Prior to N3242, modified by N3189, we said this about `unexpected()`:

> Effects: Calls the `unexpected_handler` function in effect immediately after evaluating the throw-expression (D.13.1), if called by the implementation, or calls the current `unexpected_handler`, if called by the program.

and this about `terminate()`:

> Effects: Calls the `terminate_handler` function in effect immediately after evaluating the throw-expression (18.8.3.1), if called by the implementation, or calls the current `terminate_handler` function, if called by the program.

But now in both places we say:

> Calls the current `unexpected_handler` function.

and:

> Calls the current `terminate` function.

The difference is that in C++98/03 if a destructor reset a handler during stack unwinding, that new handler was not called if the unwinding later led to `unexpected()` or `terminate()` being called. But these new words say that this new handler is called. This is an ABI-breaking change in the way exceptions are handled. Was this change intentional?

N3189 was mainly about introducing exception safety and getters for the handlers. I don't recall the issue of which handler gets called being part of the discussion.

I propose that we revert to the C++98/03 behavior in this regard, lest ABI's such as the Itanium ABI are invalidated. A mechanical way to do this is to revert bullets 9 and 12 of N3189.

[2011-12-09: Daniel comments]

There was no such semantic change intended. It was an unfortunate side effect when trying to better separate different responsibilities in the previous wording.

A related issue is 2088.

[2012-01-30: Howard comments]

The C++98/03 wording is somewhat ambiguous:

> Calls the terminate_handler function in effect immediately after evaluating the throw-expression...

There are potentially two throw-expressions being referred to here, and it is not clear if this sentence is referring to just the first or both:

1. `throw assignment-expression;`
2. `throw;`

There is ample evidence in current implementations that it is understood that only 1. was meant. But clearly both 1 and 2 could have been meant. We need a clarification. Does an execution of a rethrow (throw;) update which handlers can potentially be called?

1. `throw;` // update handlers to get_xxx()?

My opinion: Go with existing practice, and clarify what that practice is, if surveys find that everyone does the same thing. Gcc 4.2 and Apple do 1. only, and do not reset the handlers to the current handlers on throw;.

If current practice is not unanimously one way or the other, I have no strong opinion. I have not found a motivating use case for the use of any particular handler. Most applications set the handlers once at the beginning of the program and then do not change them, and so will not be impacted by whatever decision is made here.

[2014-02-15 Issaquah: Move to Review]

STL: Original change in N3242 came from trying to make set/get exception handler thread safe. The issue requests we revert to 98/03, which Howard notes was already ambiguous.

Alisdair: Issue author thinks we made this change in C++11 without taking into account Itanium ABI, which cannot implement the new semantic (without breaking compatibility).

Alisdair: original change in N3242 was trying to solve the problem of which handler is called when the handler is changing in another thread, but this turns out to be an issue in even the single-threaded case.

Pablo: despite wanting to make it thread safe, you are still changing a global

STL and Marshall confirm that there is real implementation divergance on the question, so we cannot pick just one behavior if we want to avoid breaking exisitng practice.

Alisdair: not sure who to talk to across all library vendors to fix, need more information for progress (IBM and Sun)

STL: Howard did identify a problem with the wording as well: `throw;` is a throw expression, but we typically want to re-activate the in-flight exception, not throw a new copy.

Pablo: wondering why all of this wording is here (N3189)? It looks like we were trying to handle another thread changing handler between a `throw` and `terminate` in current thread.

Alisdair: Anything working with exception handling should have used only thread-local resources, but that ship has sailed. We must account for the same exception object being re-thrown in multiple threads simultaneously, with no happens-before relationships.

Room: Why on earth would we care about exactly which way the program dies when the terminate calls are racing?!

Pablo: Reasonable to set the handler once (in `main`) and never change it.

Pablo: If willing to put lots of work into this, you could say at point of a `throw` these handlers become thread local but that is overkill. We want destructors to be able to change these handlers (if only for backwards compatibility).

Alisdair: the "do it right" is to do something per thread, but that is more work than vendors will want to do. Want to say setting handler while running multiple threads is unspecified.

Pablo: possible all we need to do is say it is always the current handler

STL: That prevents an implementation or single threaded program from calling a new handler after a `throw`, probably should say if `terminate` is called by the implementation (during EH), any handler that was current can be called. Leaves it up in the air as to when the handler is captured, supporting the diverging existing practices.

Jeffrey: use happens before terminology to avoid introducing races

STL: Give this to concurrency?

Jeffrey: It is in clause 18, generally LWG and not SG1 territory.

Alisdair: Concerned about introducing happens before into fundamental exception handling since it would affect single threaded performance as well. Want to give to concurrency or LEWG/EWG, we are into language design here.

Jeffrey: suspect LEWG won't have a strong opinion. I don't want it to be ours!!!

Pablo: Might be a case for core>

Alisdair: Would be happier if at least one core person were in the discussion.

STL: No sympathy for code that tries to guard the terminate handler.

Alisdair: We are back to set it once, globally. Want to be clear that if `set_terminate` is called just once, when EH is not active, and never changed again, then the user should get the handler from that specific call.

AlisdairM: "unspecified which handler is called if an exception is active when `set_terminate` is called." This supports existing behaviors, and guarantees which handler is called in non-conentious situations. Implicit assumption that a funtion becomes a handler only after a successful call to `set_handler`, so we are not leaving a door open to the implementation inventing entirely new handlers of its own.

Consensus.

Poll to confirm status as P1: new consensus is P3

Action: Alisdair provides new wording. Drop from P1 to P3, and move to Review.

Proposed resolution:

Amend 18.8.3.4 [terminate] as indicated:

`[[noreturn]] void terminate() noexcept;`

> Remarks: Called by the implementation when exception handling must be abandoned for any of several reasons (15.5.1) , in effect immediately after throwing the exception. May also be called directly by the program.

> Effects: Calls a `terminate_handler` function. It is unspecified which `terminate_handler` function will be called if an exception is active during a call to `set_terminate`. Otherwise c Calls the current `terminate_handler` function. [Note: A default `terminate_handler` is always considered a callable handler in this context. — end note]

Amend D.11.4 [unexpected] as indicated:

`[[noreturn]] void unexpected();`

> Remarks: Called by the implementation when a function exits via an exception not allowed by its exception-specification (15.5.2), in effect after evaluating the throw-expression (D.11.1). May also be called directly by the program.

> Effects: Calls an `unexpected_handler` function. It is unspecified which `unexpected_handler` function will be called if an exception is active during a call to `set_unexpected`. Otherwise c Calls the current `unexpected_handler` function. [Note: A default `unexpected_handler` is always considered a callable handler in this context. — end note]

### 2114. Incorrect "contextually convertible to `bool`" requirements

Section: 17.6.3.3 [nullablepointer.requirements], 24.2.3 [input.iterators], 24.2.7 [random.access.iterators], 25.1 [algorithms.general], 25.4 [alg.sorting], 30.2.1 [thread.req.paramname] Status: Open Submitter: Daniel Krügler Opened: 2011-12-09 Last modified: 2014-06-17

View all issues with Open status.

Discussion:

As of 17.6.3.1 [utility.arg.requirements] Table 17/18, the return types of the expressions

>     a == b

or

>     a < b

for types satisfying the `EqualityComparable` or `LessThanComparable` types, respectively, are required to be "convertible to `bool`" which corresponds to a copy-initialization context. But several newer parts of the library that refer to such contexts have lowered the requirements taking advantage of the new terminology of "contextually convertible to `bool`" instead, which corresponds to a direct-initialization context (In addition to "normal" direct-initialization constructions, operands of logical operations as well as `if` or `switch` conditions also belong to this special context).

One example for these new requirements are input iterators which satisfy `EqualityComparable` but also specify that the expression

>     a != b

shall be just "contextually convertible to `bool`". The same discrepancy exists for requirement set `NullablePointer` in regard to several equality-related expressions.

For random access iterators we have

> `a < b` contextually convertible to `bool`

as well as for all derived comparison functions, so strictly speaking we could have a random access iterator that does not satisfy the `LessThanComparable` requirements, which looks like an artifact to me.

Even if we keep with the existing requirements based on `LessThanComparable` or `EqualityComparable` we still would have the problem that some current specifications are actually based on the assumption of implicit convertibility instead of "explicit convertibility", e.g. 20.8.1.5 [unique.ptr.special] p3:

>     template <class T1, class D1, class T2, class D2>
>     bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

> > -3- Returns: `x.get() != y.get()`.

Similar examples exist in 20.8.1.2.2 [unique.ptr.single.dtor] p2, 20.8.1.2.3 [unique.ptr.single.asgn] p9, 20.8.1.2.4 [unique.ptr.single.observers] p1+3+8, etc.

In all these places the expressions involving comparison functions (but not those of the conversion of a `NullablePointer` to `bool`!) assume to be "convertible to `bool`". I think this is a very natural assumption and all delegations of the comparison functions of some type `X` to some other API type `Y` in third-party code does so assuming that copy-initialization semantics will just work.

The actual reason for using the newer terminology can be rooted back to LWG 556. My hypotheses is that the resolution of that issue also needs a slight correction. Why so?

The reason for opening that issue were worries based on the previous "convertible to `bool`" wording. An expressions like "`!pred(a, b)`" might not be well-formed in those situations, because `operator!` might not be accessible or might have an unusual semantics (and similarly for other logical operations). This can indeed happen with unusual proxy return types, so the idea was that the evaluation of `Predicate`, `BinaryPredicate` (25.1 [algorithms.general] p8+9), and `Compare` (25.4 [alg.sorting] p2) should be defined based on contextual conversion to `bool`. Unfortunately this alone is not sufficient: In addition, I think, we also want the predicates to be (implicitly) convertible to `bool`! Without this wording, several conditions are plain wrong, e.g. 25.2.5 [alg.find] p2, which talks about "`pred(*i) != false`" (`find_if`) and "`pred(*i) == false`" (`find_if_not`). These expressions are not within a boolean context!

While we could simply fix all these places by proper wording to be considered in a "contextual conversion to `bool`", I think that this is not the correct solution: Many third-party libraries already refer to the previous C++03 `Predicate` definition — it actually predates C++98 and is as old as the SGI specification. It seems to be a high price to pay to switch to direct initialization here instead of fixing a completely different specification problem.

A final observation is that we have another definition for a `Predicate` in 30.2.1 [thread.req.paramname] p2:

> If a parameter is `Predicate`, `operator()` applied to the actual template argument shall return a value that is convertible to `bool`.

The problem here is not that we have two different definitions of `Predicate` in the standard — this is confusing, but this fact alone is not a defect. The first (minor) problem is that this definition does not properly apply to function objects that are function pointers, because `operator()` is not defined in a strict sense. But the actually worse second problem is that this wording has the very `same` problem that has originally lead to LWG 556! We only need to look at 30.5.1 [thread.condition.condvar] p15 to recognice this:

>     while (!pred())
>       wait(lock);

The negation expression here looks very familiar to the example provided in LWG 556 and is sensitive to the same "unusual proxy" problem. Changing the 30.2.1 [thread.req.paramname] wording to a corresponding "contextual conversion to `bool`" wouldn't work either, because existing specifications rely on "convertible to `bool`", e.g. 30.5.1 [thread.condition.condvar] p32+33+42 or 30.5.2 [thread.condition.condvarany] p25+26+32+33.

To summarize: I believe that LWG 556 was not completely resolved. A pessimistic interpretation is, that even with the current wording based on "contextually convertible to `bool`" the actual problem of that issue has not been fixed. What actually needs to be required here is some normative wording that basically expresses something along the lines of:

> The semantics of any contextual conversion to `bool` shall be equivalent to the semantics of any implicit conversion to `bool`.

This is still not complete without having concepts, but it seems to be a better approximation. Another way of solving this issue would be to define a minimum requirements table with equivalent semantics. The proposed wording is a bit simpler but attempts to express the same thing.

[2012, Kona]

Agree with Daniel that we potentially broke some C++03 user code, accept the changes striking "contextually" from tables. Stefan to provide revised wording for section 25, and figure out changes to section 30.

Move to open, and then to Review when updated wording from Stefan is available.

[2012-10-12, STL comments]

1. The current proposed resolution still isn't completely satisfying. It would certainly be possible for the Standard to require these various expressions to be implicitly and contextually convertible to `bool`, but that would have a subtle consequence (which, I will argue, is undesirable - regardless of the fact that it dates all the way back to C++98/03). It would allow users to provide really wacky types to the Standard Library, with one of two effects:

   1. Standard Library implementations would have to go to great lengths to respect such wacky types, essentially using `static_cast<bool>` when invoking any predicates or comparators.

   2. Otherwise, such wacky types would be de facto nonportable, because they would make Standard Library implementations explode.

   Effect B is the status quo we're living with today. What Standard Library implementations want to do with `pred(args)` goes beyond "`if (pred(args))`" (C++03), contextually converting `pred(args)` to `bool` (C++11), or implicitly and contextually converting `pred(args)` to `bool` (the current proposed resolution). Implementations want to say things like:

   >     if (pred(args))
   >     if (!pred(args))
   >     if (cond && pred(args))
   >     if (cond && !pred(args))

   These are real examples taken from Dinkumware's implementation. There are others that would be realistic ("`pred(args) && cond`", "`cond || pred(args)`", etc.)

   Although negation was mentioned in this issue's Discussion section, and in LWG 556's, the current proposed resolution doesn't fix this problem. Requiring `pred(args)` to be implicitly and contextually convertible to `bool` doesn't prevent `operator!()` from being overloaded and returning `std::string` (as a wacky example). More ominously, it doesn't prevent `operator&&()` and `operator||()` from being overloaded and destroying short-circuiting.

2. I would like LWG input before working on Standardese for a new proposed resolution. Here's an outline of what I'd like to do:

   1. Introduce a new "concept" in 17.6.3 [utility.requirements], which I would call `BooleanTestable` in the absence of better ideas.

   2. Centralize things and reduce verbosity by having everything simply refer to `BooleanTestable` when necessary. I believe that the tables could say "Return type: `BooleanTestable`", while Predicate/BinaryPredicate/Compare would need the incantation "shall satisfy the requirements of BooleanTestable".

   3. Resolve the tug-of-war between users (who occasionally want to do weird things) and implementers (who don't want to have to contort their code) by requiring that:

      1. Given a `BooleanTestable x`, `x` is both implicitly and contextually convertible to `bool`.

      2. Given a `BooleanTestable x`, `!x` is `BooleanTestable`. (This is intentionally "recursive".)

      3. Given a `BooleanTestable x`, `bool t = x, t2(x), f = !x;` has the postcondition `t == t2 && t != f`.

      4. Given a `BooleanTestable x` and a `BooleanTestable y` of possibly different types, "`x && y`" and "`x || y`" invoke the built-in `operator&&()` and `operator||()`, triggering short-circuiting.

      5. `bool` is `BooleanTestable`.

   I believe that this simultaneously gives users great latitude to use types other than `bool`, while allowing implementers to write reasonable code in order to get their jobs done. (If I'm forgetting anything that implementers would want to say, please let me know.)

3. About requirement (I): As Daniel patiently explained to me, we need to talk about both implicit conversions and contextual conversions, because it's possible for a devious type to have both "`explicit operator bool()`" and "`operator int()`", which might behave differently (or be deleted, etc.).

4. About requirement (IV): This is kind of tricky. What we'd like to say is, "`BooleanTestable` can't ever trigger an overloaded logical operator". However, given a perfectly reasonable type `Nice` - perhaps even `bool` itself! - other code (perhaps a third-party library) could overload `operator&&(Nice, Evil)`. Therefore, I believe that the requirement should be "no first use" - the Standard Library will ask for various `BooleanTestable` types from users (for example, the result of "`first != last`" and the result of "`pred(args)`"), and as long as they don't trigger overloaded logical operators with each other, everything is awesome.

5. About requirement (V): This is possibly redundant, but it's trivial to specify, makes it easier for users to understand what they need to do ("oh, I can always achieve this with `bool`"), and provides a "base case" for requirement (IV) that may or may not be necessary. Since `bool` is `BooleanTestable`, overloading `operator&&(bool, Other)` (etc.) clearly makes the `Other` type non-`BooleanTestable`.

Previous resolution from Daniel [SUPERSEDED]:

> This wording is relative to the FDIS.

> 1. Change Table 25 — "`NullablePointer` requirements" in 17.6.3.3 [nullablepointer.requirements] as indicated:

>    Table 25 — `NullablePointer` requirements
>    Expression | Return type | Operational semantics
>    --- | --- | ---
>    `[…]`
>    `a != b` | contextually convertible to `bool` | `!(a == b)`
>    `a == np np == a` | contextually convertible to `bool` | `a == P()`
>    `a != np np != a` | contextually convertible to `bool` | `!(a == np)`

> 2. Change Table 107 — "Input iterator requirements" in 24.2.3 [input.iterators] as indicated:

>    Table 107 — Input iterator requirements (in addition to Iterator)
>    Expression | Return type | Operational semantics | Assertion/note pre-/post-condition
>    --- | --- | --- | ---
>    `a != b` | contextually convertible to `bool` | `!(a == b)` | pre: `(a, b)` is in the domain of `==`.
>    `[…]`

> 3. Change Table 111 — "Random access iterator requirements" in 24.2.7 [random.access.iterators] as indicated:

>    Table 111 — Random access iterator requirements (in addition to bidirectional iterator)
>    Expression | Return type | Operational semantics | Assertion/note pre-/post-condition
>    --- | --- | --- | ---
>    `[…]`
>    `a < b` | contextually convertible to `bool` | `b - a > 0` | `<` is a total ordering relation
>    `a > b` | contextually convertible to `bool` | `b < a` | `>` is a total ordering relation opposite to `<`.
>    `a >= b` | contextually convertible to `bool` | `!(a < b)` |
>    `a <= b` | contextually convertible to `bool` | `!(a > b)` |

> 4. Change 25.1 [algorithms.general] p8+9 as indicated:

>    > -8- The `Predicate` parameter is used whenever an algorithm expects a function object (20.9 [function.objects]) that, when applied to the result of dereferencing the corresponding iterator, returns a value testable as `true`. In other words, if an algorithm takes `Predicate pred` as its argument and first as its iterator argument, it should work correctly in the construct `pred(*first)` implicitly or contextually converted to `bool` (Clause 4 [conv]). The function object `pred` shall not apply any non-constant function through the dereferenced iterator.

>    > -9- The `BinaryPredicate` parameter is used whenever an algorithm expects a function object that when applied to the result of dereferencing two corresponding iterators or to dereferencing an iterator and type `T` when `T` is part of the signature returns a value testable as `true`. In other words, if an algorithm takes `BinaryPredicate binary_pred` as its argument and `first1` and `first2` as its iterator arguments, it should work correctly in the construct `binary_pred(*first1, *first2)` implicitly or contextually converted to `bool` (Clause 4 [conv]). `BinaryPredicate` always takes the first iterator's `value_type` as its first argument, that is, in those cases when `T` value is part of the signature, it should work correctly in the construct `binary_pred(*first1, value)` implicitly or contextually converted to `bool` (Clause 4 [conv]). `binary_pred` shall not apply any non-constant function through the dereferenced iterators.

> 5. Change 25.4 [alg.sorting] p2 as indicated:

>    > -2- `Compare` is a function object type (20.9 [function.objects]). The return value of the function call operation applied to an object of type `Compare`, when implicitly or contextually converted to `bool` (4 [conv]), yields `true` if the first argument of the call is less than the second, and `false` otherwise. `Compare comp` is used throughout for algorithms assuming an ordering relation. It is assumed that `comp` will not apply any non-constant function through the dereferenced iterator.

> 6. Change 30.2.1 [thread.req.paramname] p2 as indicated:

>    > -2- If a parameter is `Predicate`, operator() applied to the actual template argument shall return a value that is convertible to `bool` `Predicate` is a function object type (20.9 [function.objects]). The return value of the function call operation applied to an object of type `Predicate`, when implicitly or contextually converted to `bool` (4 [conv]), yields `true` if the corresponding test condition is satisfied, and `false` otherwise.

[2014-05-20, Daniel suggests concrete wording based on STL's proposal]

The presented wording follows relatively closely STL's outline with the following notable exceptions:

1. A reference to `BooleanTestable` in table "Return Type" specifications seemed very unusual to me and I found no "prior art" for this in the Standard. Instead I decided to follow the usual style to add a symbol with a specific meaning to a specific paragraph that specifies symbols and their meanings.

2. STL's requirement IV suggested to directly refer to built-in operators `&&` and `||`. In my opinion this concrete requirement isn't needed if we simply require that two `BooleanTestable` operands behave equivalently to two those operands after conversion to `bool` (each of them).

3. I couldn't find a good reason to require normatively that type `bool` meets the requirements of `BooleanTestable`: My assertion is that after having defined them, the result simply falls out of this. But to make this a bit clearer, I added also a non-normative note to these effects.

[2014-06-10, STL comments]

In the current wording I would like to see changed the suggested changes described by bullet #6:

1. In 23.2.1 [container.requirements.general] p4 undo the suggested change

2. Then change the 7 occurrences of "convertible to `bool`" in the denoted tables to "`bool`".

Proposed resolution:

This wording is relative to N3936.

1. Change 17.6.3.1 [utility.arg.requirements] p1, Table 17 — "EqualityComparable requirements", and Table 18 — "LessThanComparable requirements" as indicated:

   > -1- […] In these tables, `T` is an object or reference type to be supplied by a C++ program instantiating a template; `a`, `b`, and `c` are values of type (possibly `const`) `T`; `s` and `t` are modifiable lvalues of type `T`; `u` denotes an identifier; `rv` is an rvalue of type `T`; and `v` is an lvalue of type (possibly `const`) `T` or an rvalue of type `const T`; and `BT` denotes a type that meets the `BooleanTestable` requirements ([booleantestable.requirements]).

   > […]

   > > Table 17 — `EqualityComparable` requirements [equalitycomparable]
   > > Expression | Return type | Requirement
   > > --- | --- | ---
   > > `a == b` | convertible to `bool` `BT` | `==` is an equivalence relation, that is, it has the following properties: […]

   > […]

   > > Table 18 — `LessThanComparable` requirements [lessthancomparable]
   > > Expression | Return type | Requirement
   > > --- | --- | ---
   > > `a < b` | convertible to `bool` `BT` | `<` is a strict weak ordering relation (25.4 [alg.sorting])

2. Between 17.6.3.2 [swappable.requirements] and 17.6.3.3 [nullablepointer.requirements] insert a new sub-clause as indicated:

   > ?.?.?.? `BooleanTestable` requirements [booleantestable.requirements]

   > > -?- A `BooleanTestable` type is a boolean-like type that also supports conversions to `bool`. A type `B` meets the `BooleanTestable` requirements if the expressions described in Table ?? are valid and have the indicated semantics, and if `B` also satisfies all the other requirements of this sub-clause [booleantestable.requirements].

   > > An object `b` of type `B` can be implicitly converted to `bool` and can be contextually converted to `bool` (Clause 4). The result values of both kinds of conversions shall be equivalent.

   > > [Example: The types `bool`, `std::true_type`, and `std::bitset<>::reference` are `BooleanTestable` types. — end example]

   > > In Table ??, `B2` and `Bn` denote types (possibly equal to `B` or to each other) that meet the `BooleanTestable` requirements, `b1` denotes a (possibly `const`) value of `B`, `b2` denotes a (possibly `const`) value of `B2`, and `t1` denotes a value of type `bool`.

3. Somewhere within the new sub-clause [booleantestable.requirements] insert the following new Table (?? denotes the assigned table number):

   > Table ?? — `BooleanTestable` requirements [booleantestable]
   > Expression | Return type | Operational semantics
   > --- | --- | ---
   > `bool(b1)` | `bool` | Remarks: `bool(b1) == t1` for every value `b1` implicitly converted to `t1`.
   > `!b1` | `Bn` | Remarks: `bool(b1) == !bool(!b1)` for every value `b1`.
   > `b1 && b2` | `bool` | `bool(b1) && bool(b2)`
   > `b1 || b2` | `bool` | `bool(b1) || bool(b2)`

4. Change 17.6.3.3 [nullablepointer.requirements] p5 and Table 25 — "NullablePointer requirements" as indicated:

   > […]

   > -5- In Table 25, `u` denotes an identifier, `t` denotes a non-`const` lvalue of type `P`, `a` and `b` denote values of type (possibly `const`) `P`, and `np` denotes a value of type (possibly `const`) `std::nullptr_t`, and `BT` denotes a type that meets the `BooleanTestable` requirements ([booleantestable.requirements]).

   > […]

   > > Table 25 — `NullablePointer` requirements [nullablepointer]
   > > Expression | Return type | Operational semantics
   > > --- | --- | ---
   > > `…`
   > > `a != b` | contextually convertible to `bool` `BT` | […]
   > > `a == np` `np == a` | contextually convertible to `bool` `BT` | […]
   > > `a != np` `np != a` | contextually convertible to `bool` `BT` | […]

5. Change 20.4.2.7 [tuple.rel] as indicated;

   >     template<class... TTypes, class... UTypes>
   >     constexpr bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);

   > > -1- Requires: For all `i`, where `0 <= i` and `i < sizeof...(TTypes)`, `get<i>(t) == get<i>(u)` is a valid expression returning a type that is convertible to `bool` meets the `BooleanTestable` requirements ([booleantestable.requirements]). `sizeof...(TTypes) == sizeof...(UTypes)`.

   > > […]

   >     template<class... TTypes, class... UTypes>
   >     constexpr bool operator<(const tuple<TTypes...>& t, const tuple<UTypes...>& u);

   > > -4- Requires: For all `i`, where `0 <= i` and `i < sizeof...(TTypes)`, `get<i>(t) < get<i>(u)` and `get<i>(u) < get<i>(t)` are valid expressions returning types that are convertible to `bool` meet the `BooleanTestable` requirements ([booleantestable.requirements]). `sizeof...(TTypes) == sizeof...(UTypes)`.

   > > […]

6. Change 23.2.1 [container.requirements.general], Table 96 — "Container requirements", and Table 98 — "Optional container operations" as indicated:

   > -4- In Tables 96, 97, and 98 `X` denotes a container class containing objects of type `T`, `a` and `b` denote values of type `X`, `u` denotes an identifier, `r` denotes a non-`const` value of type `X`, and `rv` denotes a non-`const` rvalue of type `X`, and `BT` denotes a type that meets the `BooleanTestable` requirements ([booleantestable.requirements]).

   > > Table 96 — Container requirements
   > > Expression | Return type | […]
   > > --- | --- | ---
   > > `…`
   > > `a == b` | convertible to `bool` `BT` | […]
   > > `a != b` | convertible to `bool` `BT` | […]
   > > `…`
   > > `a.empty()` | convertible to `bool` `BT` | […]

   > […]

   > > Table 98 — Optional container requirements
   > > Expression | Return type | […]
   > > --- | --- | ---
   > > `…`
   > > `a < b` | convertible to `bool` `BT` | […]
   > > `a > b` | convertible to `bool` `BT` | […]
   > > `a <= b` | convertible to `bool` `BT` | […]
   > > `a >= b` | convertible to `bool` `BT` | […]

7. Change 24.2.1 [iterator.requirements.general], Table 107 — "Input iterator requirements", and Table 111 — "Random access iterator requirements" as indicated:

   > -11- In the following sections, `a` and `b` denote values of type `X` or `const X`, `difference_type` and `reference` refer to the types `iterator_traits<X>::difference_type` and `iterator_traits<X>::reference`, respectively, `n` denotes a value of `difference_type`, `u`, `tmp`, and `m` denote identifiers, `r` denotes a value of `X&`, `t` denotes a value of value type `T`, `o` denotes a value of some type that is writable to the output iterator, and `BT` denotes a type that meets the `BooleanTestable` requirements ([booleantestable.requirements]).

   > > Table 107 — Input iterator requirements
   > > Expression | Return type | […]
   > > --- | --- | ---
   > > `a != b` | contextually convertible to `bool` `BT` | […]

   > […]

   > > Table 111 — Random access iterator requirements
   > > Expression | Return type | […]
   > > --- | --- | ---
   > > `…`
   > > `a < b` | contextually convertible to `bool` `BT` | […]
   > > `a > b` | contextually convertible to `bool` `BT` | […]
   > > `a >= b` | contextually convertible to `bool` `BT` | […]
   > > `a <= b` | contextually convertible to `bool` `BT` | […]

8. Change 25.1 [algorithms.general] p8+p9 as indicated: [Drafting note: The wording change also fixes (a) unusual wording forms used ("should work") which are unclear in which sense they are imposing normative requirements and (b) the problem, that the current wording seems to allow that the predicate may mutate a call argument, if that is not a dereferenced iterator. Upon applying the new wording it became obvious that the wording has the effect that currently algorithms such as `adjacent_find`, `search_n`, `unique`, and `unique_copy` are not correctly described (because they have no iterator argument named `first1`), which could give raise to a new library issue. — end drafting note]

   > -8- The `Predicate` parameter is used whenever an algorithm expects a function object (20.9) that, when applied to the result of dereferencing the corresponding iterator, returns a value testable as `true`. In other words, i If an algorithm takes `Predicate pred` as its argument and `first` as its iterator argument, it should work correctly in the construct `pred(*first)` contextually converted to `bool` (Clause 4)the expression `pred(*first)` shall have a type that meets the `BooleanTestable` requirements ( [booleantestable.requirements]). The function object `pred` shall not apply any non-constant function through the dereferenced iterator its argument.

   > -9- The `BinaryPredicate` parameter is used whenever an algorithm expects a function object that when applied to the result of dereferencing two corresponding iterators or to dereferencing an iterator and type `T` when `T` is part of the signature returns a value testable as `true`. In other words, i If an algorithm takes `BinaryPredicate binary_pred` as its argument and `first1` and `first2` as its iterator arguments, it should work correctly in the construct `binary_pred(*first1, *first2)` contextually converted to `bool` (Clause 4)the expression `binary_pred(*first1, *first2)` shall have a type that meets the `BooleanTestable` requirements ( [booleantestable.requirements]). `BinaryPredicate` always takes the first iterator's `value_type` as its first argument, that is, in those cases when `T` value is part of the signature, it should work correctly in the construct `binary_pred(*first1, value)` contextually converted to `bool` (Clause 4)the expression `binary_pred(*first1, value)` shall have a type that meets the `BooleanTestable` requirements ( [booleantestable.requirements]). `binary_pred` shall not apply any non-constant function through the dereferenced iterators any of its arguments.

9. Change 25.4 [alg.sorting] p2 as indicated:

   > […]

   > -2- `Compare` is a function object type (20.9). The return value of the function call operation applied to an object of type `Compare`, when contextually converted to `bool`(Clause 4), yields `true` if the first argument of the call is less than the second, and `false` otherwise. `Compare comp` is used throughout for algorithms assuming an ordering relation. Let `a` and `b` denote two argument values whose types depend on the corresponding algorithm. Then the expression `comp(a, b)` shall have a type that meets the `BooleanTestable` requirements ( [booleantestable.requirements]). The return value of `comp(a, b)`, converted to `bool`, yields `true` if the first argument `a` is less than the second argument `b`, and `false` otherwise. It is assumed that `comp` will not apply any non-constant function through the dereferenced iterator any of its arguments.

   > […]

10. Change 27.5.4.2 [fpos.operations] and Table 127 — "Position type requirements" as indicated:

    > -1- Operations specified in Table 127 are permitted. In that table,

    > - `P` refers to an instance of `fpos`,

    > - […]

    > - `o` refers to a value of type `streamoff`,

    > - `BT` refers to a type that meets the `BooleanTestable` requirements ([booleantestable.requirements]),

    > - […]

    > > Table 127 — Position type requirements
    > > Expression | Return type | […]
    > > --- | --- | ---
    > > `…`
    > > `p == q` | convertible to `bool` `BT` | […]
    > > `p != q` | convertible to `bool` `BT` | […]

11. Change 30.2.1 [thread.req.paramname] p2 as indicated:

    > -2- If a parameter is `Predicate`, `operator()` applied to the actual template argument shall return a value that is convertible to `bool` `Predicate` is a function object type (20.9 [function.objects]). Let `pred` denote an lvalue of type `Predicate`. Then the expression `pred()` shall have a type that meets the `BooleanTestable` requirements ( [booleantestable.requirements]). The return value of `pred()`, converted to `bool`, yields `true` if the corresponding test condition is satisfied, and `false` otherwise.

### 2115. Undefined behaviour for `valarray` assignments with `mask_array` index?

Section: 26.6.8 [template.mask.array] Status: Open Submitter: Thomas Plum Opened: 2011-12-10 Last modified: 2014-02-11

View all issues with Open status.

Discussion:

Recently I received a Service Request (SR) alleging that one of our testcases causes an undefined behavior. The complaint is that 26.6.8 [template.mask.array] in C++11 (and the corresponding subclause in C++03) are interpreted by some people to require that in an assignment "`a[mask] = b`", the subscript `mask` and the rhs `b` must have the same number of elements.

IMHO, if that is the intended requirement, it should be stated explicitly.

In any event, there is a tiny editorial cleanup that could be made:

In C++11, 26.6.8.1 [template.mask.array.overview] para 2 mentions

> "the expression `a[mask] = b;`"

but the semicolon cannot be part of an expression. The correction could omit the semicolon, or change the word "expression" to "assignment" or "statement".

Here is the text of the SR, slightly modified for publication:

> Subject: SR01174 LVS _26322Y31 has undefined behavior [open]

> [Client:]
> The test case t263.dir/_26322Y31.cpp seems to be illegal as it has an undefined behaviour. I searched into the SRs but found SRs were not related to the topic explained in this mail (SR00324, SR00595, SR00838).

> >     const char vl[] = {"abcdefghijklmnopqrstuvwxyz"};
> >     const char vu[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
> >     const std::valarray<char> v0(vl, 27), vm5(vu, 5), vm6(vu, 6);
> >     std::valarray<char> x = v0;
> >     […]
> >     const bool vb[] = {false, false, true, true, false, true};
> >     const std::valarray<bool> vmask(vb, 6);
> >     x = v0;
> >     x[vmask] = vm5;      // ***** HERE....
> >     steq(&x[0], "abABeCghijklmnopqrstuvwxyz");
> >     x2 = x[vmask];       // ***** ....AND HERE
> >     […]

> This problem has already been discussed between [experts]: See thread http://gcc.gnu.org/ml/libstdc++/2009-11/threads.html#00051 Conclusion http://gcc.gnu.org/ml/libstdc++/2009-11/msg00099.html

> [Plum Hall:]
> Before I log this as an SR, I need to check one detail with you.

> I did read the email thread you mentioned, and I did find a citation (see INCITS ISO/IEC 14882-2003 Section 26.3.2.6 on valarray computed assignments):

> Quote: "If the array and the argument array do not have the same length, the behavior is undefined",

> But this applies to computed assignment (`*=`, `+=`, etc), not to simple assignment. Here is the C++03 citation re simple assignment:

> 26.3.2.2 valarray assignment [lib.valarray.assign]

> >     valarray<T>& operator=(const valarray<T>&);

> > > 1 Each element of the `*this` array is assigned the value of the corresponding element of the argument array. The resulting behavior is undefined if the length of the argument array is not equal to the length of the `*this` array.

> In the new C++11 (N3291), we find ...

> 26.6.2.3 valarray assignment [valarray.assign]

> >     valarray<T>& operator=(const valarray<T>& v);

> > > 1 Each element of the `*this` array is assigned the value of the corresponding element of the argument array. If the length of `v` is not equal to the length of `*this`, resizes `*this` to make the two arrays the same length, as if by calling `resize(v.size())`, before performing the assignment.

> So it looks like the testcase might be valid for C++11 but not for C++03; what do you think?

> [Client:]
> I quite agree with you but the two problems I mentioned:

> >     x[vmask] = vm5;      // ***** HERE....
> >     […]
> >     x2 = x[vmask];       // ***** ....AND HERE

> refer to `mask_array` assignment hence target the C++03 26.3.8 paragraph. Correct?

> [Plum Hall:]
> I mentioned the contrast between C++03 26.3.2.2 para 1 versus C++11 26.6.2.3 para 1.

> But in C++03 26.3.8, I don't find any corresponding restriction. Could you quote the specific requirement you're writing about?

> [Client:]
> I do notice the difference between c++03 26.3.2.2 and c++11 26.6.2.3 about assignments between different sized `valarray` and I perfectly agree with you.

> But, as already stated, this is not a simple `valarray` assignment but a `mask_array` assignment (c++03 26.3.8 / c++11 26.6.8). See c++11 quote below:

> 26.6.8 Class template mask_array
> 26.6.8.1 Class template mask_array overview
> [....]

> 1. This template is a helper template used by the mask subscript operator: `mask_array<T> valarray<T>::operator[](const valarray<bool>&)`.

> 2. It has reference semantics to a subset of an array specified by a boolean mask. Thus, the expression `a[mask] = b;` has the effect of assigning the elements of `b` to the masked elements in `a` (those for which the corresponding element in `mask` is true.)

> 26.6.8.2 mask_array assignment

> >     void operator=(const valarray<T>&) const;
> >     const mask_array& operator=(const mask_array&) const;

> > > 1 These assignment operators have reference semantics, assigning the values of the argument array elements to selected elements of the `valarray<T>` object to which it refers.

> In particular, [one of the WG21 experts] insisted on the piece "the elements of `b`".

> That is why I reported the test t263.dir/_26322Y31.cpp having an undefined behaviour.

> [Plum Hall:]
> OK, I can see that I will have to ask WG21; I will file an appropriate issue with the Library subgroup. In the meantime, I will mark this testcase as "DISPUTED" so that it is not required for conformance testing, until we get a definitive opinion.

[2012, Kona]

Moved to Open.

There appears to be a real need for clarification in the standard, and implementations differ in their current interpretation. This will need some research by implementers and a proposed resolution before further discussion is likely to be fruitful.

Proposed resolution:

### 2116. `std::swap noexcept(what?)`

Section: 20.10.4.3 [meta.unary.prop] Status: Open Submitter: Dave Abrahams Opened: 2011-12-09 Last modified: 2014-02-11

View other active issues in [meta.unary.prop].

View all other issues in [meta.unary.prop].

View all issues with Open status.

Discussion:

IMO if we specified `is_[nothrow_]constructible` in terms of a variable declaration whose validity requires destructibility, it is clearly a bug in our specification and a failure to realize the actual original intent. The specification should have been in terms of placement-new.

Daniel:
At the time of the specification this was intended and the solution is not done by removing the destruction semantics of `is_constructible`.

The design of `is_constructible` was also impacted by the previous `Constructible` concept that explicitly contained destruction semantics, because during conceptification of the library it turned out to simplify the constraints in the library because you did not need to add `Destructible` all the time. It often was implied but never spoken out in C++03.

Pure construction semantics was considered as useful as well, so `HasConstructor` did also exist and would surely be useful as trait as well.

Another example that is often overlooked: This also affects wrapper types like `pair`, `tuple`, `array` that contain potentially more than one type: This is easy to understand if you think of `T1` having a deleted destructor and `T2` having a constructor that may throw: Obviously the compiler has potentially need to use the `destructor` of `T1` in the constructor of `std::pair<T1, T2>` to ensure that the core language requirements are satisfied (All previous fully constructed sub-objects must be destructed).

The core language also honors this fact in 12.8 [class.copy] p11:

> A defaulted copy/move constructor for a class `X` is defined as deleted (8.4.3 [dcl.fct.def.delete]) if `X` has:
> […]
> — any direct or virtual base class or non-static data member of a type with a destructor that is deleted or inaccessible from the defaulted constructor,
> […]

Dave:
This is about `is_nothrow_constructible` in particular. The fact that it is foiled by not having a `noexcept` dtor is a defect.

[2012, Kona]

Move to Open.

`is_nothrow_constructible` is defined in terms of `is_constructible`, which is defined by looking at a hypothetical variable and asking whether the variable definition is known not to throw exceptions. The issue claims that this also examines the type's destructor, given the context, and thus will return `false` if the destructor can potentially throw. At least one implementation (Howard's) does return `false` if the constructor is `noexcept(true)` and the destructor is `noexcept(false)`. So that's not a strained interpretation. The issue is asking for this to be defined in terms of placement `new`, instead of in terms of a temporary object, to make it clearer that `is_nothrow_constructible` looks at the `noexcept` status of only the constructor, and not the destructor.

Sketch of what the wording would look like:

require `is_constructible`, and then also require that a placement `new` operation does not throw. (Remembering the title of this issue... What does this imply for `swap`?

If we accept this resolution, do we need any changes to `swap`?

STL argues: no, because you are already forbidden from passing anything with a throwing desturctor to `swap`.

Dietmar argues: no, not true. Maybe statically the destructor can conceivably throw for some values, but maybe there are some values known not to throw. In that case, it's correct to pass those values to `swap`.

Proposed resolution:

### 2117. `ios_base` manipulators should have `showgrouping/noshowgrouping`

Section: 22.4.2.2.2 [facet.num.put.virtuals], 27.5.3.1.2 [ios::fmtflags], 27.5.6.1 [fmtflags.manip] Status: New Submitter: Benjamin Kosnik Opened: 2011-12-15 Last modified: 2014-02-20

View all other issues in [facet.num.put.virtuals].

View all issues with New status.

Discussion:

Iostreams should include a manipulator to toggle grouping on/off for locales that support grouped digits. This has come up repeatedly and been deferred. See LWG 826 for the previous attempt.

If one is using a locale that supports grouped digits, then output will always include the generated grouping characters. However, very plausible scenarios exist where one might want to output the number, un-grouped. This is similar to existing manipulators that toggle on/off the decimal point, numeric base, or positive sign.

See some user commentary here.

[21012, Kona]

Move to Open.

This is a feature request.

Walter is slightly uncomfortable with processing feature requests through the issues lists.

Alisdair says this is far from the first feature request that has come in from the issues list.

STL: The fact that you can turn off grouping on hex output is compelling.

Marshall: if we add this flag, we'll need to update tables 87-91 as well.

STL: If it has been implemented somewhere, and it works, we'd be glad to add it.

Howard: We need to say what the default is.

Alisdair sumarizes:

(1) We want clear wording that says what the effect is of turning the flag off;

(2) what the default values are, and

(3) how this fits into tables 87-90. (and 128)

[Issaquah 2014-02-10-12: Move to LEWG]

Since this issue was filed, we have grown a new working group that is better placed to handle feature requests.

We will track such issues with an LEWG status until we get feedback from the Library Evolution Working Group.

[Issaquah 2014-02-12: LEWG discussion]

Do we think this feature should exist?
SF | F | N | A | SA
2 | 4 | 1 | 0 | 0

Think about the ABI break for adding a flag. But this could be mitigated by putting the data into an iword instead of a flag.

This needs to change Stage 2 in [facet.num.put.virtuals].

Previous resolution, which needs the above corrections:

> This wording is relative to the FDIS.

> 1. Insert in 22.4.2.2.2 [facet.num.put.virtuals] paragraph 5:

>    > Stage 1: The first action of stage 1 is to determine a conversion specifier. The tables that describe this determination use the following local variables

>    >     fmtflags flags = str.flags() ;
>    >     fmtflags basefield = (flags & (ios_base::basefield));
>    >     fmtflags uppercase = (flags & (ios_base::uppercase));
>    >     fmtflags floatfield = (flags & (ios_base::floatfield));
>    >     fmtflags showpos = (flags & (ios_base::showpos));
>    >     fmtflags showbase = (flags & (ios_base::showbase));
>    >     fmtflags showgrouping = (flags & (ios_base::showgrouping));

> 2. Change header `<ios>` synopsis, 27.5.1 [iostreams.base.overview] as indicated:

>    >     #include <iosfwd>

>    >     namespace std {
>    >       […]
>    >       // 27.5.6, manipulators:
>    >       […]
>    >       ios_base& showpoint     (ios_base& str);
>    >       ios_base& noshowpoint   (ios_base& str);
>    >       ios_base& showgrouping  (ios_base& str);
>    >       ios_base& noshowgrouping(ios_base& str);
>    >       ios_base& showpos       (ios_base& str);
>    >       ios_base& noshowpos     (ios_base& str);
>    >       […]
>    >     }

> 3. Change class `ios_base` synopsis, 27.5.3 [ios.base] as indicated:

>    >     namespace std {
>    >       class ios_base {
>    >       public:
>    >       class failure;
>    >         // 27.5.3.1.2 fmtflags
>    >         typedef T1 fmtflags;
>    >         […]
>    >         static constexpr fmtflags showpoint = unspecified ;
>    >         static constexpr fmtflags showgrouping = unspecified ;
>    >         static constexpr fmtflags showpos = unspecified ;
>    >         […]
>    >       };
>    >     }

> 4. Add a new entry to Table 122 — "`fmtflags` effects" as indicated:

>    Table 122 — `fmtflags` effects
>    Element | Effect(s) if set
>    --- | ---
>    `[…]`
>    `showpoint` | generates a decimal-point character unconditionally in generated floatingpoint output
>    `showgrouping` | generates grouping characters unconditionally in generated output
>    `[…]`

> 5. After 27.5.3.1.2 [ios::fmtflags] p12 insert the following:

>    >     ios_base& showgrouping(ios_base& str);

>    > > -?- Effects: Calls `str.setf(ios_base::showgrouping)`.

>    > > -?- Returns: `str`.

>    >     ios_base& noshowgrouping(ios_base& str);

>    > > -?- Effects: Calls `str.unsetf(ios_base::showgrouping)`.

>    > > -?- Returns: `str`.

Proposed resolution:

### 2118. [CD] `unique_ptr` for array does not support cv qualification conversion of actual argument

Section: 20.8.1.3 [unique.ptr.runtime] Status: Review Submitter: Alf P. Steinbach Opened: 2011-12-16 Last modified: 2014-07-01

View all other issues in [unique.ptr.runtime].

View all issues with Review status.

Discussion:

Addresses US 16

N3290 20.8.1.3.1 [unique.ptr.runtime.ctor] "`unique_ptr` constructors":

> These constructors behave the same as in the primary template except that they do not accept pointer types which are convertible to `pointer`. [Note: One implementation technique is to create private templated overloads of these members. — end note]

This language excludes even `pointer` itself as type for the actual argument.

But of more practical concern is that both Visual C++ 10.0 and MinGW g++ 4.1.1 reject the code below, where only an implicit cv qualification is needed, which cv qualification is supported by the non-array version:

>     #include <memory>
>     using namespace std;

>     struct T {};

>     T* foo() { return new T; }
>     T const* bar() { return foo(); }

>     int main()
>     {
>        unique_ptr< T const >       p1( bar() );        // OK
>        unique_ptr< T const [] >    a1( bar() );        // OK

>        unique_ptr< T const >       p2( foo() );        // OK
>        unique_ptr< T const [] >    a2( foo() );        // ? this is line #15
>     }

The intent seems to be clearly specified in 20.8.1.3 [unique.ptr.runtime]/1 second bullet:

> — Pointers to types derived from `T` are rejected by the constructors, and by `reset`.

But the following language in 20.8.1.3.1 [unique.ptr.runtime.ctor] then rejects far too much...

Proposed new wording of N3290 20.8.1.3.1 [unique.ptr.runtime.ctor] "`unique_ptr` constructors":

> These constructors behave the same as in the primary template except that actual argument pointers `p` to types derived from `T` are rejected by the constructors. [Note: One implementation technique is to create private templated overloads of these members. — end note]

This will possibly capture the intent better, and avoid the inconsistency between the non-array and array versions of `unique_ptr`, by using nearly the exact same phrasing as for the paragraph explaining the intent.

[2012-08-25 Geoffrey Romer comments in c++std-lib-32978]

1. The current P/R seems to intend to support at least two different implementation techniques — additional unusable templates that catch forbidden arguments or replacing existing constructors by templates that ensure ill-formed code inside the template body, when the requirements are not met. It seems unclear whether the current wording allows the second approach, though. It should be considered to allow both strategies or if that is not possible the note should be clearer.

2. The very same problem exists for the `reset` member function, but even worse, because the current specification is more than clear that the deleted `reset` function will catch all cases not equal to `pointer`. It seems confusing at best to have different policies for the constructor and for the `reset` function. In this case, the question in regard to implementation freedom mentioned above is even more important.

3. It's awkward to refer to "the constructors" twice in the same sentence; I suggest revising the sentence as "...except that they do not accept argument pointers `p` to types derived from `T`"

[2012-12-20: Geoffrey Romer comments and provides a revised resolution]

The array specialization of `unique_ptr` differs from the primary template in several ways, including the following:

- `unique_ptr<T[], D>` cannot be constructed from a plain pointer whose type is not exactly `unique_ptr<T[], D>::pointer` or `nullptr_t`.

- `unique_ptr<T[], D>` cannot be constructed from a `unique_ptr<U[], E>&&` unless `U` is exactly `T` and `E` is exactly `D`.

- `unique_ptr<T[], D>` cannot be moveassigned from a `unique_ptr<U[], E>&&` unless `U` is exactly `T` and `E` is exactly `D`.

- `unique_ptr<T[], D>::reset` cannot take an argument whose type is not exactly `unique_ptr<T[], D>::pointer` or `nullptr_t`.

- `default_delete<T[]>` cannot be constructed from a `default_delete<U[]>` unless `U` is exactly `T`.

- `default_delete<T[]>::operator()` cannot be called on a pointer whose type is not exactly `T*`.

The common intent of all these restrictions appears to be to disallow implicit conversions from pointer-to-derived-class to pointer-to-base-class in contexts where the pointer is known to point to an array, because such conversions are inherently unsafe; deleting or subscripting the result of such a conversion leads to undefined behavior (see also CWG 1504). However, these restrictions have the effect of disallowing all implicit conversions in those contexts, including most notably cv-qualification, but also user-defined conversions, and possibly others. This PR narrows all those restrictions, to disallow only unsafe pointer-to-derived to pointer-to-base conversions, while allowing all others.

I removed the nebulous language stating that certain functions "will not accept" certain arguments. Instead I use explicitly deleted template functions, which participate in overload resolution only for pointer-to-derived to pointer-to-base conversions. This is more consistent with the existing text and easier to express correctly than an approach based on declaring certain types of calls to be ill-formed, but may produce inferior compiler diagnostics.

Wherever possible, this PR defines the semantics of template specializations in terms of their differences from the primary template. This improves clarity and minimizes the risk of unintended differences (e.g. LWG 2169, which this PR also fixes). This PR also makes it explicit that the specialization inherits the description of all members, not just member functions, from the primary template and, in passing, clarifies the default definition of pointer in the specialization.

This resolution only disallows pointer-to-derived to pointer-to-base conversions between ordinary pointer types; if user-defined pointer types provide comparable conversions, it is their responsibility to ensure they are safe. This is consistent with C++'s general preference for expressive power over safety, and for assuming the user knows what they're doing; furthermore, enforcing such a restriction on user-defined types appears to be impractical without cooperation from the user.

The "base class without regard to cv-qualifiers" language is intended to parallel the specification of `std::is_base_of`.

Jonathan Wakely has a working implementation of this PR patched into libstdc++.

Previous resolution:

> This wording is relative to the FDIS.

> Change 20.8.1.3.1 [unique.ptr.runtime.ctor] as indicated:

> >     explicit unique_ptr(pointer p) noexcept;
> >     unique_ptr(pointer p, see below d) noexcept;
> >     unique_ptr(pointer p, see below d) noexcept;

> > > These constructors behave the same as in the primary template except that they do not accept pointer types which are convertible to `pointer` argument pointers `p` to types derived from `T` are rejected by the constructors. [Note: One implementation technique is to create private templated overloads of these members. — end note]

[2014-02, Issaquah]

GR: want to prevent unsafe conversions. Standard is inconsistent how it does this. for `reset()` has deleted function template capturing everything except the known-safe cases. Other functions use SFINAE. Main reason this is hard is that `unique_ptr` supports fancy pointers. Have to figure out how to handle them and what requirements to put on them. Requirements are minimal, not even required to work with `pointer_traits`.

STL surprised `pointer_traits` doesn't work

GR: ways to get fancy pointers to work is to delegate responsibility for preventing unsafe conversions to the fancy pointers themselves. Howard doesn't like that, he wants even fancy pointers to be prevented from doing unsafe conversions in `unique_ptr` contexts.

AM: Howard says `unique_ptr` was meant to be very very safe under all conditions, this open a hole in that. Howard wants to eke forward and support more, but not if we open any holes in type safety.

GR: do we need to be typesafe even for fancy types with incorrect `pointer_traits`?

AM: that would mean it's only unsafe for people who lie by providing a broken specialization of `pointer_traits`

GR: probably can't continue with ambiguity between using SFINAE and ill-formedness. Would appreciate guidance on direction used for that.

STL: difference is observable in convertibility using type traits.

STL: for `reset()` which doesn't affect convertibility ill-formed allows `static_assert`, better diagnostic. For assignment it's detectable and has traits, constraining them is better.

EN: I strongly prefer constraints than `static_asserts`

STL: if we could rely on `pointer_traits` that might be good. Alternatively could we add more machinery to deleter? make deleter say conversions are allowed, otherwise we lock down all conversions. basically want to know if converting `U` to `T` is safe.

Previous resolution [SUPERSEDED]:

> This wording is relative to N3485.

> 1. Revise 20.8.1.1.3 [unique.ptr.dltr.dflt1] as follows

>    >     namespace std {
>    >       template <class T> struct default_delete<T[]> {
>    >         constexpr default_delete() noexcept = default;
>    >         template <class U> default_delete(const default_delete<U>&) noexcept;
>    >         void operator()(T*) const;
>    >         template <class U> void operator()(U*) const = delete;
>    >       };
>    >     }

>    -?- Descriptions are provided below only for member functions that have behavior different from the primary template.

>    >     template <class U> default_delete(const default_delete<U>&) noexcept;

>    > > -?- This constructor behaves the same as in the primary template except that it shall not participate in overload resolution unless:

>    > > - `U` is an array type, and

>    > > - `V*` is implicitly convertible to `T*`, and

>    > > - `T` is not a base class of `V` (without regard to cv-qualifiers),

>    > > where `V` is the array element type of `U`.

>    > >     void operator()(T* ptr) const;

>    > > > -1- Effects: calls `delete[]` on `ptr`.

>    > > > -2- Remarks: If `T` is an incomplete type, the program is ill-formed.

>    > >     template <class U> void operator()(U*) const = delete;

>    > > > -?- Remarks: This function shall not participate in overload resolution unless `T` is a base class of `U` (without regard to cv-qualifiers).

> 2. Revise 20.8.1.2 [unique.ptr.single]/3 as follows:

>    > If the type `remove_reference<D>::type::pointer` exists, then `unique_ptr<T, D>::pointer` shall be a synonym for `remove_reference<D>::type::pointer`. Otherwise `unique_ptr<T, D>::pointer` shall be a synonym for `Telement_type*`. The type `unique_ptr<T, D>::pointer` shall satisfy the requirements of `NullablePointer` (17.6.3.3 [nullablepointer.requirements]).

> 3. Revise 20.8.1.3 [unique.ptr.runtime] as follows:

>    >     namespace std {
>    >       template <class T, class D> class unique_ptr<T[], D> {
>    >       public:
>    >         typedef see below pointer;
>    >         typedef T element_type;
>    >         typedef D deleter_type;

>    >         // 20.7.1.3.1, constructors
>    >         constexpr unique_ptr() noexcept;
>    >         explicit unique_ptr(pointer p) noexcept;
>    >         template <class U> explicit unique_ptr(U* p) = delete;
>    >         unique_ptr(pointer p, see below d) noexcept;
>    >         template <class U> unique_ptr(U* p, see below d) = delete;
>    >         unique_ptr(pointer p, see below d) noexcept;
>    >         template <class U> unique_ptr(U* p, see below d) = delete;
>    >         unique_ptr(unique_ptr&& u) noexcept;
>    >         constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
>    >         template <class U, class E> unique_ptr(unique_ptr<U, E>&& u) noexcept;

>    >         // destructor
>    >         ~unique_ptr();

>    >         // assignment
>    >         unique_ptr& operator=(unique_ptr&& u) noexcept;
>    >         template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
>    >         unique_ptr& operator=(nullptr_t) noexcept;

>    >         // 20.7.1.3.2, observers
>    >         T& operator[](size_t i) const;
>    >         pointer get() const noexcept;
>    >         deleter_type& get_deleter() noexcept;
>    >         const deleter_type& get_deleter() const noexcept;
>    >         explicit operator bool() const noexcept;

>    >         // 20.7.1.3.3 modifiers
>    >         pointer release() noexcept;
>    >         void reset(pointer p = pointer()) noexcept;
>    >         void reset(nullptr_t) noexcept;
>    >         template <class U> void reset(U*) = delete;
>    >         void swap(unique_ptr& u) noexcept;

>    >         // disable copy from lvalue
>    >         unique_ptr(const unique_ptr&) = delete;
>    >         unique_ptr& operator=(const unique_ptr&) = delete;
>    >       };
>    >     }

>    > -1- A specialization for array types is provided with a slightly altered interface.

>    > - Conversions between different types of `unique_ptr<T[], D>`from `unique_ptr<Derived[]>` to `unique_ptr<Base[]>`, where `Base` is a base class of `Derived`, from `auto_ptr`, or to or from the non-array forms of `unique_ptr` produce an ill-formed program.

>    > - Pointers to types derived from `T` are rejected by the constructors, and by `reset`.

>    > - The observers `operator*` and `operator->` are not provided.

>    > - The indexing observer `operator[]` is provided.

>    > - The default deleter will call `delete[]`.

>    > -2- Descriptions are provided below only for member functions that have behavior different members that differ from the primary template.

>    > -3- The template argument `T` shall be a complete type.

> 4. Revise 20.8.1.3.1 [unique.ptr.runtime.ctor] as follows:

>    >     explicit unique_ptr(pointer p) noexcept;
>    >     unique_ptr(pointer p, see below d) noexcept;
>    >     unique_ptr(pointer p, see below d) noexcept;
>    >     template <class U> explicit unique_ptr(U* p) = delete;
>    >     template <class U> unique_ptr(U* p, see below d) = delete;
>    >     template <class U> unique_ptr(U* p, see below d) = delete;

>    > > These constructors behave the same as in the primary template except that they do not accept pointer types which are convertible to pointer. [Note: One implementation technique is to create private templated overloads of these members. — end note]These constructors shall not participate in overload resolution unless:

>    > > - `pointer` is a pointer type, and

>    > > - `U*` is implicitly convertible to `pointer`, and

>    > > - `T` is a base class of `U` (without regard to cv-qualifiers).

>    > > The type of `d` is determined as in the corresponding non-deleted constructors.

>    >     template <class U, class E> unique_ptr(unique_ptr<U, E>&& u) noexcept;

>    > > -?- This constructor behaves the same as in the primary template, except that it shall not participate in overload resolution unless:

>    > > - `unique_ptr<U, E>::pointer` is implicitly convertible to `pointer`, and

>    > > - `U` is an array type, and

>    > > - either `D` is a reference type and `E` is the same type as `D`, or `D` is not a reference type and `E` is implicitly convertible to `D`, and

>    > > - either at least one of `pointer` and `unique_ptr<U, E>::pointer` is not a pointer type, or `T` is not a base class of the array element type of `U` (without regard to cv-qualifiers).

> 5. Insert a new sub-clause following 20.8.1.3.1 [unique.ptr.runtime.ctor] as follows:

>    ?? `unique_ptr` assignment [unique.ptr.runtime.asgn]

>    >     template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;

>    > > -?- This operator behaves the same as in the primary template, except that it shall not participate in overload resolution unless:

>    > > - `unique_ptr<U, E>::pointer` is implicitly convertible to `pointer`, and

>    > > - `U` is an array type, and

>    > > - either `D` is a reference type and `E` is the same type as `D`, or `D` is not a reference type and `E` is implicitly convertible to `D`, and

>    > > - either at least one of `pointer` and `unique_ptr<U, E>::pointer` is not a pointer type, or `T` is not a base class of the array element type of `U` (without regard to cv-qualifiers).

> 6. Revise 20.8.1.3.3 [unique.ptr.runtime.modifiers] as follows:

>    >     void reset(pointer p = pointer()) noexcept;
>    >     void reset(nullptr_t p) noexcept;
>    >     template <class U> void reset(U*) = delete;

>    > > -1- Effects: If `get() == nullptr` there are no effects. Otherwise `get_deleter()(get())`.

>    > > -2- Postcondition: `get() == p`.

>    > > -?- This function shall not participate in overload resolution unless:

>    > > - `pointer` is a pointer type, and

>    > > - `U*` is implicitly convertible to `pointer`, and

>    > > - `T` is a base class of `U` (without regard to cv-qualifiers).

[2014-06 post-Rapperswil]

As described in N4089.

Proposed resolution:

See proposed wording in N4089.

### 2119. Missing `hash` specializations for extended integer types

Section: 20.9.12 [unord.hash] Status: Open Submitter: Daniel Krügler Opened: 2011-12-16 Last modified: 2014-05-23

View all other issues in [unord.hash].

View all issues with Open status.

Discussion:

According to the header `<functional>` synopsis 20.9 [function.objects] and to the explicit description in 20.9.12 [unord.hash] class template `hash` specializations shall be provided for all arithmetic types that are not extended integer types. This is not explicitly mentioned, but neither the list nor any normative wording does include them, so it follows by implication.

What are the reasons that extended integer types are excluded? E.g. for `numeric_limits` corresponding specializations are required. I would expect that an `unordered_map` with key type `std::uintmax_t` would just work, but that depends now on whether this type is an extended integer type or not.

This issue is not asking for also providing specializations for the cv-qualified arithmetic types. While this is surely a nice-to-have feature, I consider that restriction as a more secondary problem in practice.

The proposed resolution also fixes a problem mentioned in 2109 in regard to confusing requirements on user-defined types and those on implementations.

[2012, Kona]

Move to Open.

Agreed that it's a real issue and that the proposed wording fixes it. However, the wording change is not minimal and isn't consistent with the way we fixed hash wording elsewhere.

Alisdair will provide updated wording.

[2014-05-06 Geoffrey Romer suggests alternative wording]

Previous resolution from Daniel [SUPERSEDED]:

> This wording is relative to the FDIS.

> Change 20.9.12 [unord.hash] p2 as indicated:

> >     template <> struct hash<bool>;
> >     template <> struct hash<char>;
> >     […]
> >     template <> struct hash<long double>;
> >     template <class T> struct hash<T*>;

> > > -2- Requires: the template specializations shall meet the requirements of class template `hash` (20.9.12 [unord.hash])The header `<functional>` provides definitions for specializations of the `hash` class template for each cv-unqualified arithmetic type. This header also provides a definition for a partial specialization of the `hash` class template for any pointer type. The requirements for the members of these specializations are given in sub-clause 20.9.12 [unord.hash].

Proposed resolution:

This wording is relative to N3936.

Change 20.9.12 [unord.hash] p1 as indicated:

> The unordered associative containers defined in 23.5 use specializations of the class template `hash` as the default hash function. For all object types `Key` for which there exists a specialization `hash<Key>`, and for all integral and enumeration types (7.2) `Key`, the instantiation `hash<Key>` shall: […]

### 2121. `app` for string streams

Section: 27.8.6 [stringstream.cons] Status: New Submitter: Nicolai Josuttis Opened: 2012-01-15 Last modified: 2014-02-11

View all issues with New status.

Discussion:

This issue was raised while discussing issue 1448.

Note the following program:

>     string s("s1: 123456789");
>     ostringstream s1(s, ios_base::out|ios_base::app);
>     s1 << "hello";
>     cout << s1.str() << endl;

With g++4.x it prints:

>     s1: 123456789hello

With VisualC++10 it prints:

>     hello23456789

From my intuitive understanding the flag "app" should result in the output of g++4.x. I also would read that from 27.5.3.1.4 [ios::openmode] claiming:

> `app` seek to end before each write

However in issue 1448 P.J.Plauger comments:

> I think we should say nothing special about `app` at construction time (thus leaving the write pointer at the beginning of the buffer). Leave implementers wiggle room to ensure subsequent append writes as they see fit, but don't change existing rules for initial seek position.

Note that the flag `ate` on both platforms appends "hello" to `s`.

Proposed resolution:

### 2127. Move-construction with `raw_storage_iterator`

Section: 20.7.10 [storage.iterator] Status: Open Submitter: Jonathan Wakely Opened: 2012-01-23 Last modified: 2014-02-11

View all other issues in [storage.iterator].

View all issues with Open status.

Discussion:

Aliaksandr Valialkin pointed out that `raw_storage_iterator` only supports constructing a new object from lvalues so cannot be used to construct move-only types:

>     template <typename InputIterator, typename T>
>     void move_to_raw_buffer(InputIterator first, InputIterator last, T *raw_buffer)
>     {
>       std::move(first, last, std::raw_storage_iterator<T *, T>(raw_buffer));
>     }

This could easily be solved by overloading `operator=` for rvalues.

Dave Abrahams:

`raw_storage_iterator` causes exception-safety problems when used with any generic algorithm. I suggest leaving it alone and not encouraging its use.

Proposed resolution:

This wording is relative to N3337.

1. Add a new signature to the synopsis in 20.7.10 [storage.iterator] p1:

   >     namespace std {
   >       template <class OutputIterator, class T>
   >       class raw_storage_iterator
   >         : public iterator<output_iterator_tag,void,void,void,void> {
   >       public:
   >         explicit raw_storage_iterator(OutputIterator x);

   >         raw_storage_iterator<OutputIterator,T>& operator*();
   >         raw_storage_iterator<OutputIterator,T>& operator=(const T& element);
   >         raw_storage_iterator<OutputIterator,T>& operator=(T&& element);
   >         raw_storage_iterator<OutputIterator,T>& operator++();
   >         raw_storage_iterator<OutputIterator,T> operator++(int);
   >     };
   >     }

2. Insert the new signature and a new paragraph before p4:

   >     raw_storage_iterator<OutputIterator,T>& operator=(const T& element);
   >     raw_storage_iterator<OutputIterator,T>& operator=(T&& element);

   > > -?- Requires: For the first signature `T` shall be `CopyConstructible`. For the second signature `T` shall be `MoveConstructible`.

   > > -4- Effects: Constructs a value from `element` at the location to which the iterator points.

   > > -5- Returns: A reference to the iterator.

### 2129. User specializations of `std::initializer_list`

Section: 17.6.4.2.1 [namespace.std], 18.9 [support.initlist] Status: Tentatively Ready Submitter: Richard Smith Opened: 2012-01-18 Last modified: 2014-05-02

View other active issues in [namespace.std].

View all other issues in [namespace.std].

View all issues with Tentatively Ready status.

Discussion:

Since the implementation is intended to magically synthesize instances of `std::initializer_list` (rather than by a constructor call, for instance), user specializations of this type can't generally be made to work. I can't find any wording which makes such specializations ill-formed, though, which leads me to suspect that they're technically legal under the provisions of 17.6.4.2.1 [namespace.std] p1.

[2012, Kona]

This sounds correct, but we need wording for a resolution.

Marshall Clow volunteers to produce wording.

[2014-02-19, Jonathan Wakely provides proposed wording]

[2014-03-27, Library reflector vote]

The issue has been identified as Tentatively Ready based on six votes in favour.

Proposed resolution:

This wording is relative to N3936.

1. Add new new paragraph below 18.9 [support.initlist] p2:

   > -2- An object of type `initializer_list<E>` provides access to an array of objects of type `const E`. […]

   > -?- If an explicit specialization or partial specialization of `initializer_list` is declared, the program is ill-formed.

### 2133. Attitude to overloaded comma for iterators

Section: 17.6.5.4 [global.functions] Status: Open Submitter: Yakov Galka Opened: 2012-01-25 Last modified: 2014-05-23

View all other issues in [global.functions].

View all issues with Open status.

Discussion:

17.6.5.4 [global.functions] says

> Unless otherwise specified, global and non-member functions in the standard library shall not use functions from another namespace which are found through argument-dependent name lookup (3.4.2).

This sounds clear enough. There are just two problems:

1. Both implementations I tested (VS2005 and GCC 3.4.3) do unqualified calls to the comma operator in some parts of the library with operands of user-defined types.

2. The standard itself does this in the description of some algorithms. E.g. `uninitialized_copy` is defined as:

   > Effects:

   > >     for (; first != last; ++result, ++first)
   > >       ::new (static_cast<void*>(&*result))
   > >         typename iterator_traits<ForwardIterator>::value_type(*first);

If understood literally, it is required to call `operator,(ForwardIterator, InputIterator)`.

For detailed discussion with code samples see here.

Proposal:

1. Add an exception to the rule in 17.6.5.4 [global.functions] by permitting the implementation to call the comma operator as much as it wants to. I doubt we want this. or
2. Fix the description of the said algorithms and perhaps add a note to 17.6.5.4 [global.functions] that brings attention of the implementers to avoid this pitfall.

[2013-03-15 Issues Teleconference]

Moved to Open.

There are real questions here, that may require a paper to explore and answer properly.

[2014-05-18, Daniel comments and suggests concrete wording]

Other issues, such as 2114 already follow a similar spirit as the one suggested by bullet 2 of the issue submitter. I assert that consideration of possible user-provided overloads of the comma-operator were not intended by the original wording and doing so afterwards would unnecessarily complicate a future conceptualization of the library and would needlessly restrict implementations.

I don't think that a paper is needed to solve this issue, there is a simply way to ensure that the code-semantics excludes consideration of user-provided comma operators. The provided wording below clarifies this by explicitly casting the first argument of the operator to `void`.

Proposed resolution:

This wording is relative to N3936.

1. Change 20.7.12.2 [uninitialized.copy] as indicated:

   >     template <class InputIterator, class ForwardIterator>
   >       ForwardIterator uninitialized_copy(InputIterator first, InputIterator last,
   >                                          ForwardIterator result);

   > > -1- Effects:

   > > >     for (; first != last; ++result, (void) ++first)
   > > >       ::new (static_cast<void*>(&*result))
   > > >         typename iterator_traits<ForwardIterator>::value_type(*first);

   > > […]

   >     template <class InputIterator, class Size,class ForwardIterator>
   >       ForwardIterator uninitialized_copy_n(InputIterator first, Size n,
   >                                            ForwardIterator result);

   > > -3- Effects:

   > > >     for (; n > 0; ++result, (void) ++first, --n)
   > > >       ::new (static_cast<void*>(&*result))
   > > >         typename iterator_traits<ForwardIterator>::value_type(*first);

2. Change 25.4.8 [alg.lex.comparison] p3 as indicated:

   >     template<class InputIterator1, class InputIterator2>
   >       bool
   >         lexicographical_compare(InputIterator1 first1, InputIterator1 last1,
   >                                 InputIterator2 first2, InputIterator2 last2);
   >     template<class InputIterator1, class InputIterator2, class Compare>
   >       bool
   >         lexicographical_compare(InputIterator1 first1, InputIterator1 last1,
   >                                 InputIterator2 first2, InputIterator2 last2,
   >                                 Compare comp);

   > > -3- Remarks: […]

   > > >     for ( ; first1 != last1 && first2 != last2 ; ++first1, (void) ++first2) {
   > > >       if (*first1 < *first2) return true;
   > > >       if (*first2 < *first1) return false;
   > > >     }
   > > >     return first1 == last1 && first2 != last2;

### 2136. Postconditions vs. exceptions

Section: 17.5.1 [structure] Status: Open Submitter: Jens Maurer Opened: 2012-03-08 Last modified: 2014-02-10

View all issues with Open status.

Discussion:

The front matter in clause 17 should clarify that postconditions will not hold if a standard library function exits via an exception. Postconditions or guarantees that apply when an exception is thrown (beyond the basic guarantee) are described in an "Exception safety" section.

[ 2012-10 Portland: Move to Open ]

Consensus that we do not clearly say this, and that we probably should. A likely location to describe the guarantees of postconditions could well be a new sub-clause following 17.6.4.11 [res.on.required] which serves the same purpose for requires clauses. However, we need such wording before we can make progress.

Also, see 2137 for a suggestion that we want to see a paper resolving both issues together.

Proposed resolution:

### 2137. Misleadingly constrained post-condition in the presence of exceptions

Section: 28.8.3 [re.regex.assign] Status: Open Submitter: Jonathan Wakely Opened: 2012-03-08 Last modified: 2014-02-11

View all other issues in [re.regex.assign].

View all issues with Open status.

Discussion:

The post-conditions of `basic_regex<>::assign` 28.8.3 [re.regex.assign] p16 say:

> If no exception is thrown, `flags()` returns `f` and `mark_count()` returns the number of marked sub-expressions within the expression.

The default expectation in the library is that post-conditions only hold, if there is no failure (see also 2136), therefore the initial condition should be removed to prevent any misunderstanding.

[ 2012-10 Portland: Move to Open ]

A favorable resolution clearly depends on a favorable resolution to 2136. There is also a concern that this is just one example of where we would want to apply such a wording clean-up, and which is really needed to resolve both this issue and 2136 is a paper providing the clause 17 wording that gives the guarantee for postcondition paragaraphs, and then reviews clauses 18-30 to apply that guarantee consistently. We do not want to pick up these issues piecemeal, as we risk openning many issues in an ongoing process.

Proposed resolution:

This wording is relative to N3376.

>     template <class string_traits, class A>
>       basic_regex& assign(const basic_string<charT, string_traits, A>& s,
>         flag_type f = regex_constants::ECMAScript);

> > […]

> > -15- Effects: Assigns the regular expression contained in the string `s`, interpreted according the flags specified in `f`. If an exception is thrown, `*this` is unchanged.

> > -16- Postconditions: If no exception is thrown, `flags()` returns `f` and `mark_count()` returns the number of marked sub-expressions within the expression.

### 2139. What is a user-defined type?

Section: 17.6.4.2.1 [namespace.std], 19.5 [syserr], 20.7.7.1 [allocator.uses.trait], 20.9.9.1.1 [func.bind.isbind], 20.9.9.1.2 [func.bind.isplace], 20.9.12 [unord.hash], 20.10.7.6 [meta.trans.other], 22.3.1 [locale], 22.4.1.4 [locale.codecvt], 28.12.1.4 [re.regiter.incr] Status: Open Submitter: Loïc Joly Opened: 2012-03-08 Last modified: 2014-02-20

View other active issues in [namespace.std].

View all other issues in [namespace.std].

View all issues with Open status.

Discussion:

The expression "user-defined type" is used in several places in the standard, but I'm not sure what it means. More specifically, is a type defined in the standard library a user-defined type?

From my understanding of English, it is not. From most of the uses of this term in the standard, it seem to be considered as user defined. In some places, I'm hesitant, e.g. 17.6.4.2.1 [namespace.std] p1:

> A program may add a template specialization for any standard library template to namespace `std` only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.

Does it mean we are allowed to add in the namespace `std` a specialization for `std::vector<std::pair<T, U>>`, for instance?

Additional remarks from the reflector discussion: The traditional meaning of user-defined types refers to class types and enum types, but the library actually means here user-defined types that are not (purely) library-provided. Presumably a new term - like user-provided type - should be introduced and properly defined.

[ 2012-10 Portland: Move to Deferred ]

The issue is real, in that we never define this term and rely on a "know it when I see it" intuition. However, there is a fear that any attempt to pin down a definition is more likely to introduce bugs than solve them - getting the wording for this precisely correct is likely far more work than we are able to give it.

There is unease at simple closing as NAD, but not real enthusiasm to provide wording either. Move to Deferred as we are not opposed to some motivated individual coming back with full wording to review, but do not want to go out of our way to encourage someone to work on this in preference to other issues.

[2014-02-20 Re-open Deferred issues as Priority 4]

Proposed resolution:

### 2146. Are reference types `Copy`/`Move-Constructible`/`Assignable` or `Destructible`?

Section: 17.6.3.1 [utility.arg.requirements] Status: Open Submitter: Nikolay Ivchenkov Opened: 2012-03-23 Last modified: 2014-06-17

View other active issues in [utility.arg.requirements].

View all other issues in [utility.arg.requirements].

View all issues with Open status.

Discussion:

According to 17.6.3.1 [utility.arg.requirements] p1

> The template definitions in the C++ standard library refer to various named requirements whose details are set out in tables 17-24. In these tables, `T` is an object or reference type to be supplied by a C++ program instantiating a template; `a`, `b`, and `c` are values of type (possibly `const`) `T`; `s` and `t` are modifiable lvalues of type `T`; `u` denotes an identifier; `rv` is an rvalue of type `T`; and `v` is an lvalue of type (possibly `const`) `T` or an rvalue of type `const T`.

Is it really intended that `T` may be a reference type? If so, what should `a`, `b`, `c`, `s`, `t`, `u`, `rv`, and `v` mean? For example, are "`int &`" and "`int &&`" `MoveConstructible`?

As far as I understand, we can explicitly specify template arguments for `std::swap` and `std::for_each`. Can we use reference types there?

1. >     #include <iostream>
   >     #include <utility>

   >     int main()
   >     {
   >       int x = 1;
   >       int y = 2;
   >       std::swap<int &&>(x, y); // undefined?
   >       std::cout << x << " " << y << std::endl;
   >     }

2. >     #include <algorithm>
   >     #include <iostream>
   >     #include <iterator>
   >     #include <utility>

   >     struct F
   >     {
   >       void operator()(int n)
   >       {
   >         std::cout << n << std::endl;
   >         ++count;
   >       }
   >       int count;
   >     } f;

   >     int main()
   >     {
   >       int arr[] = { 1, 2, 3 };
   >       auto&& result = std::for_each<int *, F &&>( // undefined?
   >         std::begin(arr),
   >         std::end(arr),
   >         std::move(f));
   >       std::cout << "count: " << result.count << std::endl;
   >     }

Are these forms of usage well-defined?

Let's also consider the following constructor of `std::thread`:

>     template <class F, class ...Args>
>     explicit thread(F&& f, Args&&... args);

> > Requires: `F` and each `Ti` in `Args` shall satisfy the `MoveConstructible` requirements.

When the first argument of this constructor is an lvalue (e.g. a name of a global function), template argument for `F` is deduced to be lvalue reference type. What should "`MoveConstructible`" mean with regard to an lvalue reference type? Maybe the wording should say that `std::decay<F>::type` and each `std::decay<Ti>::type` (where `Ti` is an arbitrary item in `Args`) shall satisfy the `MoveConstructible` requirements?

[2013-03-15 Issues Teleconference]

Moved to Open.

The questions raised by the issue are real, and should have a clear answer.

Proposed resolution:

### 2151. `basic_string<>::swap` semantics ignore allocators

Section: 21.4.1 [string.require] Status: Open Submitter: Robert Shearer Opened: 2012-04-13 Last modified: 2014-02-11

View all other issues in [string.require].

View all issues with Open status.

Discussion:

In C++11, `basic_string` is not described as a "container", and is not governed by the allocator-aware container semantics described in sub-clause 23.2 [container.requirements]; as a result, and requirements or contracts for the `basic_string` interface must be documented in Clause 21 [strings].

Sub-clause 21.4.6.8 [string::swap] defines the `swap` member function with no requirements, and with guarantees to execute in constant time without throwing. Fulfilling such a contract is not reasonable in the presence of unequal non-propagating allocators.

In contrast, 23.2.1 [container.requirements.general] p7 declares the behavior of member `swap` for containers with unequal non-propagating allocators to be undefined.

Resolution proposal:

Additional language from Clause 23 [containers] should probably be copied to Clause 21 [strings]. I will refrain from an exactly recommendation, however, as I am raising further issues related to the language in Clause 23 [containers].

[2013-03-15 Issues Teleconference]

Moved to Open.

Alisdair has offered to provide wording.

Telecon notes that 23.2.1 [container.requirements.general]p13 says that `string` is an allocator-aware container.

Proposed resolution:

### 2152. Instances of standard container types are not swappable

Section: 17.6.3.2 [swappable.requirements], 23.2.1 [container.requirements.general] Status: Open Submitter: Robert Shearer Opened: 2012-04-13 Last modified: 2014-02-10

View all other issues in [swappable.requirements].

View all issues with Open status.

Discussion:

Sub-clause 17.6.3.2 [swappable.requirements] defines two notions of swappability: a binary version defining when two objects are swappable with one another, and a unary notion defining whether an object is swappable (without qualification), with the latter definition requiring that the object satisfy the former with respect to all values of the same type.

Let `T` be a container type based on a non-propagating allocator whose instances do not necessarily compare equal. Then sub-clause 23.2.1 [container.requirements.general] p7 implies that no object `t` of type `T` is swappable (by the unary definition).

Throughout the standard it is the unary definition of "swappable" that is listed as a requirement (with the exceptions of 20.2.2 [utility.swap] p4, 20.3.2 [pairs.pair] p31, 20.4.2.3 [tuple.swap] p2, 25.3.3 [alg.swap] p2, and 25.3.3 [alg.swap] p6, which use the binary definition). This renders many of the mutating sequence algorithms of sub-clause 25.3 [alg.modifying.operations], for example, inapplicable to sequences of standard container types, even where every element of the sequence is swappable with every other.

Note that this concern extends beyond standard containers to all future allocator-based types.

Resolution proposal:

I see two distinct straightforward solutions:

1. Modify the requirements of algorithms from sub-clause 25.3 [alg.modifying.operations], and all other places that reference the unary "swappable" definition, to instead use the binary "swappable with" definition (over a domain appropriate to the context). The unary definition of "swappable" could then be removed from the standard.
2. Modify sub-clause 23.2.1 [container.requirements.general] such that objects of standard container types are "swappable" by the unary definition.

I favor the latter solution, for reasons detailed in the following issue.

[ 2012-10 Portland: Move to Open ]

The issue is broader than containers with stateful allocotors, although they are the most obvious example contained within the standard itself. The basic problem is that once you have a stateful allocator, that does not `propagate_on_swap`, then whether two objects of this type can be swapped with well defined behavior is a run-time property (the allocators compare equal) rather than a simple compile-time property that can be deduced from the type. Strictly speaking, any type where the nature of swap is a runtime property does not meet the `swappable` requirements of C++11, although typical sequences of such types are going to have elements that are all `swappable with` any other element in the sequence (using our other term of art for specifying requirements) as the common case is a container of elements who all share the same allocator.

The heart of the problem is that the `swappable` requirments demand that any two objects of the same type be `swappable with` each other, so if any two such objects would not be `swappable with` each other, then the whole type is never `swappable`. Many algorithms in clause 25 are specified in terms of `swappable` which is essentially an overspecification as all they actually need is that any element in the sequence is `swappable with` any other element in the sequence.

At this point Howard joins the discussion and points out that the intent of introducing the two swap-related terms was to support `vector<bool>::reference` types, and we are reading something into the wording that was never intended. Consuses is that regardless of the intent, that is what the words today say.

There is some support to see a paper reviewing the whole of clause 25 for this issue, and other select clauses as may be necessary.

There was some consideration to introducing a note into the front of clause 25 to indicate `swappable` requirements in the clause should be interpreted to allow such awkward types, but ultimately no real enthusiasm for introducing a `swappable for clause 25` requirement term, especially if it confusingly had the same name as a term used with a subtly different meaning through the rest of the standard.

There was no enthusiasm for the alternate resolution of requiring containers with unequal allocators that do not propagate provide a well-defined swap behavior, as it is not believed to be possible without giving `swap` linear complexity for such values, and even then would require adding the constraint that the container element types are CopyConstructible.

Final conclusion: move to open pending a paper from a party with a strong interest in stateful allocators.

Proposed resolution:

### 2153. Narrowing of the non-member `swap` contract

Section: 20.2.2 [utility.swap], 17.6.3.2 [swappable.requirements], 23.2.1 [container.requirements.general] Status: Open Submitter: Robert Shearer Opened: 2012-04-13 Last modified: 2014-02-11

View all issues with Open status.

Discussion:

Sub-clause 20.2.2 [utility.swap] defines a non-member 'swap' function with defined behavior for all `MoveConstructible` and `MoveAssignable` types. It does not guarantee constant-time complexity or `noexcept` in general, however this definition does render all objects of `MoveConstructible` and `MoveAssignable` type swappable (by the unary definition of sub-clause 17.6.3.2 [swappable.requirements]) in the absence of specializations or overloads.

The overload of the non-member `swap` function defined in Table 96, however, defines semantics incompatible with the generic non-member `swap` function, since it is defined to call a member `swap` function whose semantics are undefined for some values of `MoveConstructible` and `MoveAssignable` types.

The obvious (perhaps naive) interpretation of sub-clause 17.6.3.2 [swappable.requirements] is as a guide to the "right" semantics to provide for a non-member `swap` function (called in the context defined by 17.6.3.2 [swappable.requirements] p3) in order to provide interoperable user-defined types for generic programming. The standard container types don't follow these guidelines.

More generally, the design in the standard represents a classic example of "contract narrowing". It is entirely reasonable for the contract of a particular `swap` overload to provide more guarantees, such as constant-time execution and `noexcept`, than are provided by the `swap` that is provided for any `MoveConstructible` and `MoveAssignable` types, but it is not reasonable for such an overload to fail to live up to the guarantees it provides for general types when it is applied to more specific types. Such an overload or specialization in generic programming is akin to an override of an inherited virtual function in OO programming: violating a superclass contract in a subclass may be legal from the point of view of the language, but it is poor design and can easily lead to errors. While we cannot prevent user code from providing overloads that violate the more general `swap` contract, we can avoid doing so within the library itself.

My proposed resolution is to draw a sharp distinction between member `swap` functions, which provide optimal performance but idiosyncratic contracts, and non-member `swap` functions, which should always fulfill at least the contract of 20.2.2 [utility.swap] and thus render objects swappable. The member `swap` for containers with non-propagating allocators, for example, would offer constant-time guarantees and `noexcept` but would only offer defined behavior for values with allocators that compare equal; non-member `swap` would test allocator equality and then dispatch to either member `swap` or `std::swap` depending on the result, providing defined behavior for all values (and rendering the type "swappable"), but offering neither the constant-time nor the `noexcept` guarantees.

[2013-03-15 Issues Teleconference]

Moved to Open.

This topic deserves more attention than can be given in the telocon, and there is no proposed resolution.

Proposed resolution:

### 2154. What exactly does compile-time complexity imply?

Section: 26.5.1.3 [rand.req.urng] Status: New Submitter: John Salmon Opened: 2012-04-26 Last modified: 2014-02-11

View all other issues in [rand.req.urng].

View all issues with New status.

Discussion:

The expressions `G::min()` and `G::max()` in Table 116 in 26.5.1.3 [rand.req.urng] are specified as having "compile-time" complexity.

It is not clear what, exactly, this requirement implies. If a URNG has a method:

>     static int min();

then is the method required to have a `constexpr` qualifier? I believe the standard would benefit from clarification of this point.

Proposed resolution:

### 2155. Macro `__bool_true_false_are_defined` should be removed

Section: 18.10 [support.runtime] Status: Open Submitter: Thomas Plum Opened: 2012-04-30 Last modified: 2014-02-11

View other active issues in [support.runtime].

View all other issues in [support.runtime].

View all issues with Open status.

Discussion:

Since C99, the C standard describes a macro named `__bool_true_false_are_defined`.

In the process of harmonizing C++11 with C99, this name became part of the C++ standard.

I propose that all mention of this name should be removed from the C and C++ standards.

Here's the problem: The name was originally proposed as a transition tool, so that the headers for a project could contain lines like the following.

>     #if !defined(__bool_true_false_are_defined)
>     #define bool int /* or whatever */
>     #define true 1
>     #define false 0
>     #endif

Then when the project was compiled by a "new" compiler that implemented `bool` as defined by the evolving C++98 or C99 standards, those lines would be skipped; but when compiled by an "old" compiler that didn't yet provide `bool`, `true`, and `false`, then the `#define`'s would provide a simulation that worked for most purposes.

It turns out that there is an unfortunate ambiguity in the name. One interpretation is as shown above, but a different reading says "bool, true, and false are #define'd", i.e. that the meaning of the macro is to assert that these names are macros (not built-in) ... which is true in C, but not in C++.

In C++11, the name appears in parentheses followed by a stray period, so some editorial change is needed in any event:

18.10 [support.runtime] para 1:

> Headers `<csetjmp>` (nonlocal jumps), `<csignal>` (signal handling), `<cstdalign>` (alignment), `<cstdarg>` (variable arguments), `<cstdbool>` (`__bool_true_false_are_defined`). `<cstdlib>` (runtime environment `getenv()`, `system()`), and `<ctime>` (system clock `clock()`, `time()`) provide further compatibility with C code.

However, para 2 says

> "The contents of these headers are the same as the Standard C library headers `<setjmp.h>`, `<signal.h>`, `<stdalign.h>`, `<stdarg.h>`, `<stdbool.h>`, `<stdlib.h>`, and `<time.h>`, respectively, with the following changes:",

and para 8 says

> "The header `<cstdbool>` and the header `<stdbool.h>` shall not define macros named `bool`, `true`, or `false`."

Thus para 8 doesn't exempt the C++ implementation from the arguably clear requirement of the C standard, to provide a macro named `__bool_true_false_are_defined` defined to be 1.

Real implementations of the C++ library differ, so the user cannot count upon any consistency; furthermore, the usefulness of the transition tool has faded long ago.

That's why my suggestion is that both C and C++ standards should eliminate any mention of `__bool_true_false_are_defined`. In that case, the name belongs to implementers to provide, or not, as they choose.

[2013-03-15 Issues Teleconference]

Moved to Open.

While not strictly necessary, the clean-up look good.

We would like to hear from our C liaison before moving on this issue though.

Proposed resolution:

### 2156. Unordered containers' `reserve(n)` reserves for `n-1` elements

Section: 23.2.5 [unord.req] Status: Open Submitter: Daniel James Opened: 2012-05-07 Last modified: 2014-03-03

View other active issues in [unord.req].

View all other issues in [unord.req].

View all issues with Open status.

Discussion:

I think that unordered containers' `reserve` doesn't quite do what it should. I'd expect after calling `x.reserve(n)` to be able to insert `n` elements without invalidating iterators. But as the standard is written (I'm looking at n3376), I think the guarantee only holds for `n-1` elements.

For a container with `max_load_factor` of `1`, `reserve(n)` is equivalent to `rehash(ceil(n/1))`, ie. `rehash(n)`. `rehash(n)` requires that the bucket count is `>= n`, so it can be `n` (Table 103). The rule is that `insert` shall not affect the validity of iterators if `(N + n) < z * B` (23.2.5 [unord.req] p15). But for this case the two sides of the equation are equal, so `insert` can affect the validity of iterators.

[2013-03-16 Howard comments and provides wording]

Given the following:

>     LF := load_factor()
>     MLF := max_load_factor()
>     S := size()
>     B := bucket_count()

>     LF == S/B

The container has an invariant:

>     LF <= MLF

Therefore:

>     MLF >= S/B
>     S <= MLF * B
>     B >= S/MLF

[2013-03-15 Issues Teleconference]

Moved to Open.

Howard to provide rationale and potentally revised wording.

[2012-02-12 Issaquah : recategorize as P3]

Jonathon Wakely: submitter is Boost.Hash maintainer. Think it's right.

Marshall Clow: even if wrong it's more right than what we have now

Geoffrey Romer: issue is saying rehash should not leave container in such a state that a notional insertion of zero elements should not trigger a rehash

AJM: e.g. if you do a range insert from an empty range

AJM: we don't have enough brainpower to do this now, so not priority zero

Recategorised as P3

Proposed resolution:

This wording is relative to N3485.

1. In 23.2.5 [unord.req] Table 103 — Unordered associative container requirements, change the post-condition in the row for `a.rehash(n)` to:

   > Post: `a.bucket_count() >= a.size() / a.max_load_factor()` and `a.bucket_count() >= n`.

2. In 23.2.5 [unord.req]/p15 change

   > The `insert` and `emplace` members shall not affect the validity of iterators if `(N+n) <= z * B`, where `N` is the number of elements in the container prior to the insert operation, `n` is the number of elements inserted, `B` is the container's bucket count, and `z` is the container's maximum load factor.

### 2157. How does `std::array<T,0>` initialization work when `T` is not default-constructible?

Section: 23.3.2.8 [array.zero] Status: Open Submitter: Daryle Walker Opened: 2012-05-08 Last modified: 2014-02-11

View all other issues in [array.zero].

View all issues with Open status.

Discussion:

Objects of `std::array<T,N>` are supposed to be initialized with aggregate initialization (when not the destination of a copy or move). This clearly works when `N` is positive. What happens when `N` is zero? To continue using an (inner) set of braces for initialization, a `std::array<T,0>` implementation must have an array member of at least one element, and let default initialization take care of those secret elements. This cannot work when `T` has a set of constructors and the default constructor is deleted from that set. Solution: Add a new paragraph in 23.3.2.8 [array.zero]:

> The unspecified internal structure of array for this case shall allow initializations like:

> >     array<T, 0> a = { };

> and said initializations must be valid even when `T` is not default-constructible.

[2012, Portland: Move to Open]

Some discussion to understand the issue, which is that implementations currently have freedom to implement an empty `array` by holding a dummy element, and so might not support value initialization, which is surprising when trying to construct an empty container. However, this is not mandated, it is an unspecified implementation detail.

Jeffrey points out that the implication of 23.3.2.1 [array.overview] is that this initialization syntax must be supported by empty `array` objects already. This is a surprising inference that was not obvious to the room, but consensus is that the reading is accurate, so the proposed resolution is not necessary, although the increased clarity may be useful.

Further observation is that the same clause effectively implies that `T` must always be DefaultConstructible, regardless of `N` for the same reasons - as an initializer-list may not supply enough values, and the remaining elements must all be value initialized.

Concern that we are dancing angels on the head of pin, and that relying on such subtle implications in wording is not helpful. We need a clarification of the text in this area, and await wording.

Proposed resolution:

This wording is relative to N3376.

Add the following new paragraph between the current 23.3.2.8 [array.zero] p1 and p2:

> -1- `array` shall provide support for the special case `N == 0`.

> -?- The unspecified internal structure of `array` for this case shall allow initializations like:

> >     array<T, 0> a = { };

> and said initializations must be valid even when `T` is not default-constructible.

> -2- In the case that `N == 0`, `begin() == end() ==` unique value. The return value of `data()` is unspecified.

> -3- The effect of calling `front()` or `back()` for a zero-sized array is undefined.

> -4- Member function `swap()` shall have a noexcept-specification which is equivalent to `noexcept(true)`.

### 2158. Conditional copy/move in `std::vector`

Section: 23.3.6.3 [vector.capacity] Status: New Submitter: Nikolay Ivchenkov Opened: 2012-05-08 Last modified: 2014-02-11

View other active issues in [vector.capacity].

View all other issues in [vector.capacity].

View all issues with New status.

Discussion:

There are various operations on `std::vector` that can cause elements of the vector to be moved from one location to another. A move operation can use either rvalue or const lvalue as argument; the choice depends on the value of `!is_nothrow_move_constructible<T>::value && is_copy_constructible<T>::value`, where `T` is the element type. Thus, some operations on `std::vector` (e.g. 'resize' with single parameter, 'reserve', 'emplace_back') should have conditional requirements. For example, let's consider the requirement for 'reserve' in N3376 – 23.3.6.3 [vector.capacity]/2:

> Requires: `T` shall be `MoveInsertable` into `*this`.

This requirement is not sufficient if an implementation is free to select copy constructor when `!is_nothrow_move_constructible<T>::value && is_copy_constructible<T>::value` evaluates to true. Unfortunately, `is_copy_constructible` cannot reliably determine whether `T` is really copy-constructible. A class may contain public non-deleted copy constructor whose definition does not exist or cannot be instantiated successfully (e.g., `std::vector<std::unique_ptr<int>>` has copy constructor, but this type is not copy-constructible). Thus, the actual requirements should be:

- if `!is_nothrow_move_constructible<T>::value && is_copy_constructible<T>::value` then `T` shall be `CopyInsertable` into `*this`;

- otherwise `T` shall be `MoveInsertable` into `*this`.

Maybe it would be useful to introduce a new name for such conditional requirement (in addition to "`CopyInsertable`" and "`MoveInsertable`").

Proposed resolution:

### 2160. Unintended destruction ordering-specification of `resize`

Section: 23.3.6.3 [vector.capacity] Status: Review Submitter: Daniel Krügler Opened: 2012-06-07 Last modified: 2014-07-01

View other active issues in [vector.capacity].

View all other issues in [vector.capacity].

View all issues with Review status.

Discussion:

As part of resolving LWG issue 2033 a wording change was done for `resize()` to respect the problem mentioned in the question:

> Does a call to 'void resize(size_type sz)' of `std::vector` require the element type to be `MoveAssignable` because the call `erase(begin() + sz, end())` mentioned in the Effects paragraph would require the element type to be `MoveAssignable`?

The wording change was to replace in 23.3.3.3 [deque.capacity] and 23.3.6.3 [vector.capacity]:

> -1- Effects: If `sz <= size()`, equivalent to `erase(begin() + sz, end())`; […]

by:

> -1- Effects: If `sz <= size()`, equivalent to calling `pop_back() size() - sz` times. […]

The overlooked side-effect of this wording change is that this implies a destruction order of the removed elements to be in reverse order of construction, but the previous version did not impose any specific destruction order due to the way how the semantics of `erase` is specified in Table 100.

Given the program:

>     #include <vector>
>     #include <iostream>

>     struct Probe {
>       int value;
>       Probe() : value(0) {}
>       Probe(int value) : value(value) {}
>       ~Probe() { std::cout << "~Probe() of " << value << std::endl; }
>     };

>     int main() {
>       std::vector<Probe> v;
>       v.push_back(Probe(1));
>       v.push_back(Probe(2));
>       v.push_back(Probe(3));
>       std::cout << "---" << std::endl;
>       v.resize(0);
>     }

the last three lines of the output for every compiler I tested was:

>     ~Probe() of 1
>     ~Probe() of 2
>     ~Probe() of 3

but a conforming implementation would now need to change this order to

>     ~Probe() of 3
>     ~Probe() of 2
>     ~Probe() of 1

This possible stringent interpretation makes sense, because one can argue that sequence containers (or at least `std::vector`) should have the same required destruction order of it's elements, as elements of a C array or controlled by memory deallocated with an array `delete` have. I also learned that libc++ does indeed implement `std::vector::resize` in a way that the second output form is observed.

While I agree that required reverse-destruction would better mimic the natural behaviour of `std::vector` this was not required in C++03 and this request may be too strong. My current suggestion would be to restore the effects of the previous wording in regard to the destruction order, because otherwise several currently existing implementations would be broken just because of this additional requirement.

[2013-03-15 Issues Teleconference]

Moved to Open.

Jonathan says that he believes this is a valid issue.

Walter wonders if this was intended when we made the previous change - if so, this would be NAD.

Jonathan said that Issue 2033 doesn't mention ordering.

Walter then asked if anyone is really unhappy that we're destroying items in reverse order of construction.

Jonathan points out that this conflicts with existing practice (libstc++, but not libc++).

Jonathan asked for clarification as to whether this change was intended by 2033.

[2014-06 Rapperswil]

Daniel points out that the ordering change was not intended.

General agreement that implementations should not be required to change.

[2014-06-28 Daniel provides alternative wording]

Proposed resolution:

This wording is relative to N3936.

1. Change 23.3.3.3 [deque.capacity] as indicated: [Drafting note: The chosen wording form is similar to that for `forward_list`. Note that the existing Requires element already specifies the necessary operational requirements on the value type. — end drafting note]

   >     void resize(size_type sz);

   > > -1- Effects: If `sz <= size()`, erases the last `size() - sz` elements from the sequence equivalent to calling `pop_back() size() - sz` times. Otherwise If `size() <= sz`, appends `sz - size()` default-inserted elements to the sequence.

   > > […]

   >     void resize(size_type sz, const T& c);

   > > -3- Effects: If `sz <= size()`, erases the last `size() - sz` elements from the sequence equivalent to calling `pop_back() size() - sz` times. Otherwise If `size() < sz`, appends `sz - size()` copies of `c` to the sequence.

   > > […]

2. Change 23.3.6.3 [vector.capacity] as indicated: [Drafting note: See `deque` for the rationale of the used wording. — end drafting note]

   >     void resize(size_type sz);

   > > -12- Effects: If `sz <= size()`, erases the last `size() - sz` elements from the sequence equivalent to calling `pop_back() size() - sz` times. Otherwise If `size() < sz`, appends `sz - size()` default-inserted elements to the sequence.

   > > […]

   >     void resize(size_type sz, const T& c);

   > > -15- Effects: If `sz <= size()`, erases the last `size() - sz` elements from the sequence equivalent to calling `pop_back() size() - sz` times. Otherwise If `size() < sz`, appends `sz - size()` copies of `c` to the sequence.

   > > […]

### 2161. `const` equivalence of `std::map`

Section: 23.4 [associative], 23.5 [unord] Status: New Submitter: Bjarne Stroustrup Opened: 2012-06-18 Last modified: 2014-02-11

View all other issues in [associative].

View all issues with New status.

Discussion:

As described in the reflector discussion c++std-core-21860 consider the following example:

>     map<const int, int> mci{};
>     map<int, int> mi = mci; // ??
>     mci[1] = 2;
>     mi[1] = 2;

Should it be required that the marked initialization is well-formed? As a possible solution this could be realized by an alias template:

>     template <class K, class T>
>     struct OriginalMap { […] };

>     template <class K, class T>
>     using ImprovedMap = OriginalMap<const K, T>;

Proposed resolution:

### 2164. What are the semantics of `vector.emplace(vector.begin(), vector.back())`?

Section: 23.3.6.5 [vector.modifiers], 23.2 [container.requirements] Status: New Submitter: Howard Hinnant Opened: 2012-07-07 Last modified: 2014-02-11

View other active issues in [vector.modifiers].

View all other issues in [vector.modifiers].

View all issues with New status.

Discussion:

Nikolay Ivchenkov recently brought the following example on the std-discussion newsgroup, asking whether the following program well-defined:

>     #include <iostream>
>     #include <vector>

>     int main()
>     {
>       std::vector<int> v;
>       v.reserve(4);
>       v = { 1, 2, 3 };
>       v.emplace(v.begin(), v.back());
>       for (int x : v)
>         std::cout << x << std::endl;
>     }

Nikolay Ivchenkov:

I think that an implementation of `vector`'s 'emplace' should initialize an intermediate object with `v.back()` before any shifts take place, then perform all necessary shifts and finally replace the value pointed to by `v.begin()` with the value of the intermediate object. So, I would expect the following output:

>     3
>     1
>     2
>     3

GNU C++ 4.7.1 and GNU C++ 4.8.0 produce other results:

>     2
>     1
>     2
>     3

Howard Hinnant:

I believe Nikolay is correct that vector should initialize an intermediate object with `v.back()` before any shifts take place. As Nikolay pointed out in another email, this appears to be the only way to satisfy the strong exception guarantee when an exception is not thrown by `T`'s copy constructor, move constructor, copy assignment operator, or move assignment operator as specified by 23.3.6.5 [vector.modifiers]/p1. I.e. if the emplace construction throws, the vector must remain unaltered.

That leads to an implementation that tolerates objects bound to the function parameter pack of the `emplace` member function may be elements or sub-objects of elements of the container.

My position is that the standard is correct as written, but needs a clarification in this area. Self-referencing `emplace` should be legal and give the result Nikolay expects. The proposed resolution of LWG 760 is not correct.

Proposed resolution:

### 2165. `std::atomic<X>` requires `X` to be nothrow default constructible

Section: 29.5 [atomics.types.generic], 29.6 [atomics.types.operations] Status: Core Submitter: Jonathan Wakely Opened: 2012-07-19 Last modified: 2013-10-15

View all other issues in [atomics.types.generic].

Discussion:

As raised in c++std-lib-32781, this fails to compile even though the default constructor is not used:

>     #include <atomic>

>     struct X {
>       X() noexcept(false) {}
>       X(int) { }
>     };

>     std::atomic<X> x(3);

This is because `atomic<T>`'s default constructor is declared to be non-throwing and is explicitly-defaulted on its first declaration:

>     atomic() noexcept = default;

This is ill-formed if the implicitly-declared default constructor would not be non-throwing.

Possible solutions:

1. Add nothrow default constructible to requirements for template argument of the generic `atomic<T>`
2. Remove `atomic<T>::atomic()` from the overload set if `T` is not nothrow default constructible.
3. Remove `noexcept` from `atomic<T>::atomic()`, allowing it to be deduced (but the default constructor is intended to be always noexcept)
4. Do not default `atomic<T>::atomic()` on its first declaration (but makes the default constructor user-provided and so prevents `atomic<T>` being trivial)
5. A core change to allow the mismatched exception specification if the default constructor isn't used (see c++std-core-21990)

[2012, Portland: move to Core]

Recommend referring to core to see if the constructor `noexcept` mismatch can be resolved there. The issue is not specific to concurrency.

Proposed resolution:

### 2166. Heap property underspecified?

Section: 25.4.6 [alg.heap.operations] Status: New Submitter: Peter Sommerlad Opened: 2012-07-09 Last modified: 2014-02-11

View all other issues in [alg.heap.operations].

View all issues with New status.

Discussion:

Another similar issue to the `operator<` vs greater in `nth_element` but not as direct occurs in 25.4.6 [alg.heap.operations]:

> -1- A heap is a particular organization of elements in a range between two random access iterators `[a,b)`. Its two key properties are:

> 1. There is no element greater than `*a` in the range and
> 2. `*a` may be removed by `pop_heap()`, or a new element added by `push_heap()`, in O(log(`N`)) time.

As noted by Richard Smith, it seems that the first bullet should read:

> `*a` is not less than any element in the range

Even better the heap condition could be stated here directly, instead of leaving it unspecified, i.e.,

> Each element at `(a+2*i+1)` and `(a+2*i+2)` is less than the element at `(a+i)`, if those elements exist, for `i>=0`.

But may be that was may be intentional to allow other heap organizations?

See also follow-up discussion of c++std-lib-32780.

Proposed resolution:

### 2168. Inconsistent specification of `uniform_real_distribution` constructor

Section: 26.5.8.2.2 [rand.dist.uni.real] Status: Open Submitter: Marshall Clow Opened: 2012-07-14 Last modified: 2014-06-19

View all issues with Open status.

Discussion:

uniform_real says in 26.5.8.2.2 [rand.dist.uni.real] p1:

> A `uniform_real_distribution` random number distribution produces random numbers `x`, `a ≤ x < b`,

but also that (26.5.8.2.2 [rand.dist.uni.real] p2):

>     explicit uniform_real_distribution(RealType a = 0.0, RealType b = 1.0);

> > -2- Requires: `a ≤ b` and `b - a ≤ numeric_limits<RealType>::max()`.

If you construct a `uniform_real_distribution<RealType>(a, b)` where there are no representable numbers between 'a' and 'b' (using `RealType`'s representation) then you cannot satisfy 26.5.8.2.2 [rand.dist.uni.real].

An obvious example is when `a == b`.

Proposed resolution:

### 2170. Aggregates cannot be `DefaultConstructible`

Section: 17.6.3.1 [utility.arg.requirements] Status: Ready Submitter: Daniel Krügler Opened: 2012-07-19 Last modified: 2014-03-03

View other active issues in [utility.arg.requirements].

View all other issues in [utility.arg.requirements].

View all issues with Ready status.

Discussion:

The lack of the definition of the `DefaultConstructible` requirements in C++03 was fixed by LWG 724 at a time where the core rules of list-initialization were slightly different than today, at that time value-initialization (shortly) was the primary rule for class types, i.e. just before applying CWG 1301, CWG 1324, and CWG 1368.

The order in 8.5.4 [dcl.init.list] p3 was changed to respect aggregate initialization, but that had the side-effect that formally aggregate types cannot satisfy the `DefaultConstructible` requirements anymore, because we require that

>     T u{};

value-initializes the object `u`.

Of-course exclusion of aggregates was not intended, therefore I suggest to extend the requirements in Table 19 (17.6.3.1 [utility.arg.requirements]) for empty aggregate-initialization as well.

[ 2012-10 Portland: Move to Core ]

We are not qualified to pick apart the Core rules quickly at this point, but the consensus is that if the core language has changed in this manner, then the fix should similarly be applied in Core - this is not something that we want users of the language to have to say every time they want to Value initialize (or aggregate initialize) an object.

More to Open until we get a clear response from Core, Alisdair to file an issue with Mike.

[2013-04 Bristol: Back to Library]

The Core Working group opened, discussed, and resolved CWG 1578 as NAD for this library-related problem: Empty aggregate initialization and value-initialization are different core language concepts, and this difference can be observed (e.g. for a type with a deleted default-constructor).

[2014-02-15 Issaquah: Move to Ready]

AM: core says still LWG issue, wording has been non-controversial, move to ready?

NJ: what about durations? think they are ok

Ville: `pair` and a few other have value initialize

AM: look at core 1578

AM: value initialize would require `()`, remove braces from third row?

STL: no

PH: core has new issue on aggregates and non-aggregates.

AM: right, they said does not affect this issue

NJ: why ok with `pair` and `tuple`?

STL: will use `()`, `tuple` of aggregates with deleted constructor is ill-formed

Ville: aggregate with reference can't have `()`

STL: `{}` would be an issue too

Ville: aggregate with reference will have `()` deleted implicitly

Move to Ready.

Proposed resolution:

This wording is relative to N3691.

Change Table 19 in 17.6.3.1 [utility.arg.requirements] as indicated:

Table 19 — `DefaultConstructible` requirements [defaultconstructible]
Expression | Post-condition
--- | ---
`T t;` | object `t` is default-initialized
`T u{};` | object `u` is value-initialized or aggregate-initialized
`T()` `T{}` | a temporary object of type `T` is value-initialized or aggregate-initialized

### 2173. The meaning of operator + in the description of the algorithms

Section: 25 [algorithms] Status: New Submitter: Nikolay Ivchenkov Opened: 2012-08-01 Last modified: 2014-06-17

View all other issues in [algorithms].

View all issues with New status.

Discussion:

According to 25.1 [algorithms.general]/12,

> In the description of the algorithms operators `+` and `-` are used for some of the iterator categories for which they do not have to be defined. In these cases the semantics of `a+n` is the same as that of

> >     X tmp = a;
> >     advance(tmp, n);
> >     return tmp;

There are several places where such operator `+` is applied to an output iterator — for example, see the description of `std::copy`:

>     template<class InputIterator, class OutputIterator>
>     OutputIterator copy(InputIterator first, InputIterator last,
>                         OutputIterator result);

> > -1- Effects: Copies elements in the range `[first,last)` into the range `[result,result + (last - first))` starting from `first` and proceeding to `last`. For each non-negative integer `n < (last - first)`, performs `*(result + n) = *(first + n)`.

`std::advance` is not supposed to be applicable to output iterators, so we need a different method of description.

See also message c++std-lib-32908.

[2014-06-07 Daniel comments and provides wording]

The specification for output iterators is somewhat tricky, because here a sequence of increments is required to be combined with intervening assignments to the dereferenced iterator. I tried to respect this fact by using a conceptual assignment operation as part of the specification.

Another problem in the provided as-if-code is the question which requirements are imposed on `n`. Unfortunately, the corresponding function `advance` is completely underspecified in this regard, so I couldn't borrow wording from it. We cannot even assume here that `n` is the difference type of the iterator, because for output iterators there is no requirements for this associated type to be defined. The presented wording attempts to minimize assumptions, but still can be considered as controversial.

Proposed resolution:

This wording is relative to N3936.

1. Change 25.1 [algorithms.general] around p12 as indicated:

   > -12- In the description of the algorithms operators `+` and `-` are used for some of the iterator categories for which they do not have to be defined. In these cases the semantics of `a+n` is the same as that of

   > >     X tmp = a;
   > >     advance(tmp, n);
   > >     return tmp;

   > when `X` meets the input iterator requirements (24.2.3 [input.iterators]), otherwise it is the same as that of

   > >     X tmp = a;
   > >     for (auto i = n; i; ++tmp, (void) --i)
   > >       *tmp = Expr(i);
   > >     return tmp;

   > where `Expr(i)` denotes the `n-i`-th expression that is assigned to for the corresponding algorithm; and that of `b-a` is the same as of

   > >     return distance(a, b);

### 2178. `Allocator` requirement changes not mentioned Annex C

Section: 17.6.3.5 [allocator.requirements], C.4 [diff.library] Status: Open Submitter: Nevin Liber Opened: 2012-08-14 Last modified: 2014-02-11

View other active issues in [allocator.requirements].

View all other issues in [allocator.requirements].

View all issues with Open status.

Discussion:

Given that a number of things were removed from the allocator requirements (`reference`, `const_reference`, `address()` in 17.6.3.5 [allocator.requirements]), it seems that these incompatible changes should be mentioned in Annex C.4 [diff.library], more specifically in [diff.cpp03].

[ 2012-10 Portland: Move to Open ]

It was clearly pointed out by Bill during the C++11 process that our change to allocator requirements potentially broke 3rd party user containers written to expect C++03 allocators, or rather, an allocator written to the minimal requirements of C++11 might not be guaranteed to work with a container written to the previous rules. This was a trade-off in making allocaters easier to write by use of the `allocator_traits` framework.

This probably does merit a write-up in Annex C, and we look forward to seeing wording. Until then, the best we can do is move the issue to Open.

Proposed resolution:

### 2179. `enable_shared_from_this` and construction from raw pointers

Section: 20.8.2.5 [util.smartptr.enab], 20.8.2.2.1 [util.smartptr.shared.const] Status: Open Submitter: Daniel Krügler Opened: 2012-08-16 Last modified: 2014-02-11

View all issues with Open status.

Discussion:

On reflector message c++std-lib-32927, Matt Austern asked whether the following example should be well-defined or not

>     struct X : public enable_shared_from_this<X> { };
>     auto xraw = new X;
>     shared_ptr<X> xp1(xraw);
>     shared_ptr<X> xp2(xraw);

pointing out that 20.8.2.2.1 [util.smartptr.shared.const] does not seem to allow it, since `xp1` and `xp2` aren't allowed to share ownership, because each of them is required to have `use_count() == 1`. Despite this wording it might be reasonable (and technical possible) to implement that request.

On the other hand, there is the non-normative note in 20.8.2.5 [util.smartptr.enab] p11 (already part of TR1):

> The `shared_ptr` constructors that create unique pointers can detect the presence of an `enable_shared_from_this` base and assign the newly created `shared_ptr` to its `__weak_this member`.

Now according to the specification in 20.8.2.2.1 [util.smartptr.shared.const] p3-7:

>     template<class Y> explicit shared_ptr(Y* p);

the notion of creating unique pointers can be read to be included by this note, because the post-condition of this constructor is `unique() == true`. Evidence for this interpretation seems to be weak, though.

Howard Hinnant presented the counter argument, that actually the following is an "anti-idiom" and it seems questionable to teach it to be well-defined in any case:

>     auto xraw = new X;
>     shared_ptr<X> xp1(xraw);
>     shared_ptr<X> xp2(xraw);

He also pointed out that the current post-conditions of the affected `shared_ptr` constructor would need to be reworded.

It needs to be decided, which direction to follow. If this idiom seems too much broken to be supported, the note could be improved. If it should be supported, the constructors in 20.8.2.2.1 [util.smartptr.shared.const] need a careful analysis to ensure that post-conditions are correct.

Several library implementations currently do not support this example, instead they typically cause a crash. Matt points out that there are currently no explicit requirements imposed on `shared_ptr` objects to prevent them from owning the same underlying object without sharing the ownership. It might be useful to add such a requirement.

[2013-03-15 Issues Teleconference]

Moved to Open.

More discussion is needed to pick a direction to guide a proposed resolution.

[2013-05-09 Jonathan comments]

The note says the newly created `shared_ptr` is assigned to the `weak_ptr` member. It doesn't say before doing that the `shared_ptr` should check if the `weak_ptr` is non-empty and possibly share ownership with some other pre-existing `shared_ptr`.

Proposed resolution:

### 2181. Exceptions from seed sequence operations

Section: 26.5.1.2 [rand.req.seedseq], 26.5.3 [rand.eng], 26.5.4 [rand.adapt] Status: Open Submitter: Daniel Krügler Opened: 2012-08-18 Last modified: 2014-05-23

View all other issues in [rand.req.seedseq].

View all issues with Open status.

Discussion:

LWG issue 2180 points out some deficiences in regard to the specification of the library-provided type `std::seed_seq` regarding exceptions, but there is another specification problem in regard to general types satisfying the seed sequence constraints (named `SSeq`) as described in 26.5.1.2 [rand.req.seedseq].

26.5.3 [rand.eng] p3 and 26.5.4.1 [rand.adapt.general] p3 say upfront:

> Except where specified otherwise, no function described in this section 26.5.3 [rand.eng]/26.5.4 [rand.adapt] throws an exception.

This constraint causes problems, because the described templates in these sub-clauses depend on operations of `SSeq::generate()` which is a function template, that depends both on operations provided by the implementor of `SSeq` (e.g. of `std::seed_seq`), and those of the random access iterator type provided by the caller. With class template `linear_congruential_engine` we have just one example for a user of `SSeq::generate()` via:

>     template<class Sseq>
>     linear_congruential_engine<>::linear_congruential_engine(Sseq& q);

>     template<class Sseq>
>     void linear_congruential_engine<>::seed(Sseq& q);

None of these operations has an exclusion rule for exceptions.

As described in 2180 the wording for `std::seed_seq` should and can be fixed to ensure that operations of `seed_seq::generate()` won't throw except from operations of the provided iterator range, but there is no corresponding "safety belt" for user-provided `SSeq` types, since 26.5.1.2 [rand.req.seedseq] does not impose no-throw requirements onto operations of seed sequences.

1. A quite radical step to fix this problem would be to impose general no-throw requirements on the expression `q.generate(rb,re)` from Table 115, but this is not as simple as it looks initially, because this function again depends on general types that are mutable random access iterators. Typically, we do not impose no-throw requirements on iterator operations and this would restrict general seed sequences where exceptions are not a problem. Furthermore, we do not impose comparable constraints for other expressions, like that of the expression `g()` in Table 116 for good reasons, e.g. `random_device::operator()` explicitly states when it throws exceptions.

2. A less radical variant of the previous suggestion would be to add a normative requirement on the expression `q.generate(rb,re)` from Table 115 that says: "Throws nothing if operations of `rb` and `re` do not throw exceptions". Nevertheless we typically do not describe conditional Throws elements in proper requirement sets elsewhere (Container requirements excluded, they just describe the containers from Clause 23) and this may exclude resonable implementations of seed sequences that could throw exceptions under rare situations.

3. The iterator arguments provided to `SSeq::generate()` for operations in templates of 26.5.3 [rand.eng] and 26.5.4 [rand.adapt] are under control of implementations, so we could impose stricter exceptions requirements on `SSeq::generate()` for `SSeq` types that are used to instantiate member templates in 26.5.3 [rand.eng] and 26.5.4 [rand.adapt] solely.

4. We simply add extra wording to the introductive parts of 26.5.3 [rand.eng] and 26.5.4 [rand.adapt] that specify that operations of the engine (adaptor) templates that depend on a template parameter `SSeq` throw no exception unless `SSeq::generate()` throws an exception.

Given these options I would suggest to apply the variant described in the fourth bullet.

The proposed resolution attempts to reduce a lot of the redundancies of requirements in the introductory paragraphs of 26.5.3 [rand.eng] and 26.5.4 [rand.adapt] by introducing a new intermediate sub-clause "Engine and engine adaptor class templates" following sub-clause 26.5.2 [rand.synopsis]. This approach also solves the problem that currently 26.5.3 [rand.eng] also describes requirements that apply for 26.5.4 [rand.adapt] (Constrained templates involving the `Sseq` parameters).

[2013-04-20, Bristol]

Remove the first bullet point:

> ?- Throughout this sub-clause general requirements and conventions are described that apply to every class template specified in sub-clause 26.5.3 [rand.eng] and 26.5.4 [rand.adapt]. Phrases of the form "in those sub-clauses" shall be interpreted as equivalent to "in sub-clauses 26.5.3 [rand.eng] and 26.5.4 [rand.adapt]".

Replace "in those sub-clauses" with "in sub-clauses 26.5.3 [rand.eng] and 26.5.4 [rand.adapt]".

Find another place for the wording.

Daniel: These are requirements on the implementation not on the types. I'm not comfortable in moving it to another place without double checking.

Improve the text (there are 4 "for"s): for copy constructors, for copy assignment operators, for streaming operators, and for equality and inequality operators are not shown in the synopses.

Move the information of this paragraph to the paragraphs it refers to:

> "-?- Descriptions are provided in those sub-clauses only for engine operations that are not described in 26.5.1.4 [rand.req.eng], for adaptor operations that are not described in 26.5.1.5 [rand.req.adapt], or for operations where there is additional semantic information. In particular, declarations for copy constructors, for copy assignment operators, for streaming operators, and for equality and inequality operators are not shown in the synopses."

Alisdair: I prefer duplication here than consolidation/reference to these paragraphs.

The room showed weakly favjust or for duplication.

Previous resolution from Daniel [SUPERSEDED]:

> 1. Add a new sub-clause titled "Engine and engine adaptor class templates" following sub-clause 26.5.2 [rand.synopsis] (but at the same level) and add one further sub-clause "General" as child of the new sub-clause as follows:

>    Engine and engine adaptor class templates [rand.engadapt]

>    General [rand.engadapt.general]

>    > -?- Throughout this sub-clause general requirements and conventions are described that apply to every class template specified in sub-clause 26.5.3 [rand.eng] and 26.5.4 [rand.adapt]. Phrases of the form "in those sub-clauses" shall be interpreted as equivalent to "in sub-clauses 26.5.3 [rand.eng] and 26.5.4 [rand.adapt]".

>    > -?- Except where specified otherwise, the complexity of each function specified in those sub-clauses is constant.

>    > -?- Except where specified otherwise, no function described in those sub-clauses throws an exception.

>    > -?- Every function described in those sub-clauses that has a function parameter `q` of type `SSeq&` for a template type parameter named `SSeq` that is different from type `std::seed_seq` throws what and when the invocation of `q.generate` throws.

>    > -?- Descriptions are provided in those sub-clauses only for engine operations that are not described in 26.5.1.4 [rand.req.eng], for adaptor operations that are not described in 26.5.1.5 [rand.req.adapt], or for operations where there is additional semantic information. In particular, declarations for copy constructors, for copy assignment operators, for streaming operators, and for equality and inequality operators are not shown in the synopses.

>    > -?- Each template specified in those sub-clauses requires one or more relationships, involving the value(s) of its non-type template parameter(s), to hold. A program instantiating any of these templates is ill-formed if any such required relationship fails to hold.

>    > -?- For every random number engine and for every random number engine adaptor `X` defined in those sub-clauses:

>    > - if the constructor

>    >   >     template <class Sseq> explicit X(Sseq& q);

>    >   is called with a type `Sseq` that does not qualify as a seed sequence, then this constructor shall not participate in overload resolution;

>    > - if the member function

>    >   >     template <class Sseq> void seed(Sseq& q);

>    >   is called with a type `Sseq` that does not qualify as a seed sequence, then this function shall not participate in overload resolution;

>    > The extent to which an implementation determines that a type cannot be a seed sequence is unspecified, except that as a minimum a type shall not qualify as a seed sequence if it is implicitly convertible to `X::result_type`.

> 2. Edit the contents of sub-clause 26.5.3 [rand.eng] as indicated:

>    > -1- Each type instantiated from a class template specified in this section 26.5.3 [rand.eng] satisfies the requirements of a random number engine (26.5.1.4 [rand.req.eng]) type and the general implementation requirements specified in sub-clause [rand.engadapt.general].

>    > -2- Except where specified otherwise, the complexity of each function specified in this section 26.5.3 [rand.eng] is constant.

>    > -3- Except where specified otherwise, no function described in this section 26.5.3 [rand.eng] throws an exception.

>    > -4- Descriptions are provided in this section 26.5.3 [rand.eng] only for engine operations that are not described in 26.5.1.4 [rand.req.eng] […]

>    > -5- Each template specified in this section 26.5.3 [rand.eng] requires one or more relationships, involving the value(s) of its non-type template parameter(s), to hold. […]

>    > -6- For every random number engine and for every random number engine adaptor `X` defined in this subclause (26.5.3 [rand.eng]) and in sub-clause 26.5.3 [rand.eng]: […]

> 3. Edit the contents of sub-clause 26.5.4.1 [rand.adapt.general] as indicated:

>    > -1- Each type instantiated from a class template specified in this section 26.5.3 [rand.eng]26.5.4 [rand.adapt] satisfies the requirements of a random number engine adaptor (26.5.1.5 [rand.req.adapt]) type and the general implementation requirements specified in sub-clause [rand.engadapt.general].

>    > -2- Except where specified otherwise, the complexity of each function specified in this section 26.5.4 [rand.adapt] is constant.

>    > -3- Except where specified otherwise, no function described in this section 26.5.4 [rand.adapt] throws an exception.

>    > -4- Descriptions are provided in this section 26.5.4 [rand.adapt] only for engine operations that are not described in 26.5.1.5 [rand.req.adapt] […]

>    > -5- Each template specified in this section 26.5.4 [rand.adapt] requires one or more relationships, involving the value(s) of its non-type template parameter(s), to hold. […]

[2014-02-09, Daniel provides alternative resolution]

[2014-05-22, Daniel syncs with recent WP]

Proposed resolution:

This wording is relative to N3936.

1. Edit the contents of sub-clause 26.5.3 [rand.eng] as indicated:

   > -1- Each type instantiated from a class template specified in this section 26.5.3 [rand.eng] satisfies the requirements of a random number engine (26.5.1.4 [rand.req.eng]) type.

   > -2- Except where specified otherwise, the complexity of each function specified in this section 26.5.3 [rand.eng] is constant.

   > -3- Except where specified otherwise, no function described in this section 26.5.3 [rand.eng] throws an exception.

   > -?- Every function described in this section 26.5.3 [rand.eng] that has a function parameter `q` of type `Sseq&` for a template type parameter named `Sseq` that is different from type `std::seed_seq` throws what and when the invocation of `q.generate` throws.

   > -4- Descriptions are provided in this section 26.5.3 [rand.eng] only for engine operations that are not described in 26.5.1.4 [rand.req.eng] or for operations where there is additional semantic information. In particular, declarations for copy constructors, for copy assignment operators, for streaming operators, and for equality operators, and inequality operators are not shown in the synopses.

   > -5- Each template specified in this section 26.5.3 [rand.eng] requires one or more relationships, involving the value(s) of its non-type template parameter(s), to hold. A program instantiating any of these templates is ill-formed if any such required relationship fails to hold.

   > -6- For every random number engine and for every random number engine adaptor `X` defined in this subclause (26.5.3 [rand.eng]) and in sub-clause 26.5.4 [rand.adapt]:

   > - if the constructor

   >   >     template <class Sseq> explicit X(Sseq& q);

   >   is called with a type `Sseq` that does not qualify as a seed sequence, then this constructor shall not participate in overload resolution;

   > - if the member function

   >   >     template <class Sseq> void seed(Sseq& q);

   >   is called with a type `Sseq` that does not qualify as a seed sequence, then this function shall not participate in overload resolution;

   > The extent to which an implementation determines that a type cannot be a seed sequence is unspecified, except that as a minimum a type shall not qualify as a seed sequence if it is implicitly convertible to `X::result_type`.

2. Edit the contents of sub-clause 26.5.4.1 [rand.adapt.general] as indicated:

   > -1- Each type instantiated from a class template specified in this section 26.5.3 [rand.eng]26.5.4 [rand.adapt] satisfies the requirements of a random number engine adaptor (26.5.1.5 [rand.req.adapt]) type.

   > -2- Except where specified otherwise, the complexity of each function specified in this section 26.5.4 [rand.adapt] is constant.

   > -3- Except where specified otherwise, no function described in this section 26.5.4 [rand.adapt] throws an exception.

   > -?- Every function described in this section 26.5.4 [rand.adapt] that has a function parameter `q` of type `Sseq&` for a template type parameter named `Sseq` that is different from type `std::seed_seq` throws what and when the invocation of `q.generate` throws.

   > -4- Descriptions are provided in this section 26.5.4 [rand.adapt] only for adaptor operations that are not described in section 26.5.1.5 [rand.req.adapt] or for operations where there is additional semantic information. In particular, declarations for copy constructors, for copy assignment operators, for streaming operators, and for equality operators, and inequality operators are not shown in the synopses.

   > -5- Each template specified in this section 26.5.4 [rand.adapt] requires one or more relationships, involving the value(s) of its non-type template parameter(s), to hold. A program instantiating any of these templates is ill-formed if any such required relationship fails to hold.

3. Edit the contents of sub-clause 26.5.8.1 [rand.dist.general] p2 as indicated: [Drafting note: These editorial changes are just for consistency with those applied to 26.5.3 [rand.eng] and 26.5.4.1 [rand.adapt.general] — end drafting note]

   > -2- Descriptions are provided in this section 26.5.8 [rand.dist] only for distribution operations that are not described in 26.5.1.6 [rand.req.dist] or for operations where there is additional semantic information. In particular, declarations for copy constructors, for copy assignment operators, for streaming operators, and for equality operators, and inequality operators are not shown in the synopses.

### 2183. Muddled allocator requirements for `match_results` constructors

Section: 28.10.1 [re.results.const], 28.10.6 [re.results.all] Status: New Submitter: Pete Becker Opened: 2012-08-29 Last modified: 2014-02-11

View other active issues in [re.results.const].

View all other issues in [re.results.const].

View all issues with New status.

Discussion:

28.10.1 [re.results.const] p1 says:

> In all `match_results` constructors, a copy of the `Allocator` argument shall be used for any memory allocation performed by the constructor or member functions during the lifetime of the object.

There are three constructors:

>     match_results(const Allocator& = Allocator());
>     match_results(const match_results& m);
>     match_results(match_results&& m) noexcept;

The second and third constructors do no have an `Allocator` argument, so despite the "all `match_results` constructors", it is not possible to use "the `Allocator` argument" for the second and third constructors.

The requirements for those two constructors also does not give any guidance. The second constructor has no language about allocators, and the third states that the stored `Allocator` value is move constructed from `m.get_allocator()`, but doesn't require using that allocator to allocate memory.

The same basic problem recurs in 28.10.6 [re.results.all], which gives the required return value for `get_allocator()`:

> Returns: A copy of the `Allocator` that was passed to the object's constructor or, if that allocator has been replaced, a copy of the most recent replacement.

Again, the second and third constructors do not take an `Allocator`, so there is nothing that meets this requirement when those constructors are used.

Proposed resolution:

### 2184. Muddled allocator requirements for `match_results` assignments

Section: 28.10.1 [re.results.const], 28.10.6 [re.results.all] Status: New Submitter: Pete Becker Opened: 2012-08-29 Last modified: 2014-02-11

View other active issues in [re.results.const].

View all other issues in [re.results.const].

View all issues with New status.

Discussion:

The effects of the two assignment operators are specified in Table 141. Table 141 makes no mention of allocators, so, presumably, they don't touch the target object's allocator. That's okay, but it leaves the question: `match_results::get_allocator()` is supposed to return "A copy of the Allocator that was passed to the object's constructor or, if that allocator has been replaced, a copy of the most recent replacement"; if assignment doesn't replace the allocator, how can the allocator be replaced?

Proposed resolution:

### 2189. Throwing `swap` breaks unordered containers' state

Section: 23.2.5.1 [unord.req.except] Status: Open Submitter: Alisdair Meredith Opened: 2012-09-23 Last modified: 2014-02-11

View all issues with Open status.

Discussion:

The hash functor and key-comparison functor of unordered containers are allowed to throw on `swap`.

23.2.5.1 [unord.req.except]p3 "For unordered associative containers, no `swap` function throws an exception unless that exception is thrown by the swap of the container's Hash or Pred object (if any)."

In such a case we must offer the basic exception safety guarantee, where both objects are left in valid but unspecified states, and no resources are leaked. This yields a corrupt, un-usable container if the first `swap` succeeds, but the second fails by throwing, as the functors form a matched pair.

So our basic scenario is first, swap the allocators if the allocators propagate on swap, according to `allocator_traits`. Next we swap the pointers to our internal hash table data structures, so that they match the allocators that allocated them. (Typically, this operation cannot throw). Now our containers are back in a safely destructible state if an exception follows.

Next, let's say we swap the hash functor, and that throws. We have a corrupt data structure, in that the buckets are not correctly indexed by the correct functors, lookups will give unpredicatable results etc. We can safely restore a usable state by forcibly clearing each container - which does not leak resources and leaves us with two (empty but) usable containers.

Now let us assume that the hasher swap succeeds. Next we swap the equality comparator functor, and this too could throw. The important point to bear in mind is that these two functors form an important pairing - two objects that compare equal by the equality functor must also hash to the same value. If we swap one without the other, we most likely leave the container in an unusable state, even if we clear out all elements.

1. A colleague pointed out that the solution for this is to dynamically allocate the two functors, and then we need only swap pointers, which is not a throwing operation. And if we don't want to allocate on default construction (a common QoI request), we might consider moving to a dynamically allocated functors whenever `swap` is called, or on first insertion. Of course, allocating memory in `swap` is a whole new can of worms, but this does not really sound like the design we had intended.

2. The simplest option is to say that we do not support hasher or equality functors that throw on ADL `swap`. Note that the requirement is simply to not throw, rather than to be explicitly marked as `noexcept`. Throwing functors are allowed, so long as we never use values that would actually manifest a throw when used in an unordered container.

Pablo went on to give me several more options, to be sure we have a full set to consider:

3. Disallow one or the other functor from throwing. In that case, the possibly-throwing functor must be swapped first, then the other functor, the allocator, and the data pointer(s) afterwards (in any order -- there was a TC that allocator assignment and swap may not throw if the corresponding propagation trait is true.). Of course, the question becomes: which functor is allowed to throw and which one is not?

4. Require that any successful functor `swap` be reliably reversible. This is very inventive. I know of no other place in the standard where such a requirement is stated, though I have occasionally wanted such a guarantee.

5. Allow a failed swap to leave the containers in a state where future insertions may fail for reasons other than is currently allowed. Specifically, if the hash and equality functors are out of sync, all insertions will fail. Presumably some "incompletely swapped" exception would be thrown. This is "slightly" inventive, although people have been discussing "radioactive" states for a while.

[2013-03-15 Issues Teleconference]

Moved to Open.

Proposed resolution:

### 2191. Incorrect specification of `match_results(match_results&&)`

Section: 28.10.1 [re.results.const] Status: New Submitter: Pete Becker Opened: 2012-10-02 Last modified: 2014-02-11

View other active issues in [re.results.const].

View all other issues in [re.results.const].

View all issues with New status.

Discussion:

28.10.1 [re.results.const]/3: "Move-constructs an object of class `match_results` satisfying the same postconditions as Table 141."

Table 141 lists various member functions and says that their results should be the results of the corresponding member function calls on `m`. But `m` has been moved from, so the actual requirement ought to be based on the value that `m` had before the move construction, not on `m` itself.

In addition to that, the requirements for the copy constructor should refer to Table 141.

Ganesh:

Also, the requirements for move-assignment should refer to Table 141. Further it seems as if in Table 141 all phrases of "for all integers `n < m.size()`" should be replaced by "for all unsigned integers `n < m.size()`".

Proposed resolution:

### 2192. Validity and return type of `std::abs(0u)` is unclear

Section: 26.8 [c.math] Status: Open Submitter: Daniel Krügler Opened: 2012-10-02 Last modified: 2014-02-11

View other active issues in [c.math].

View all other issues in [c.math].

View all issues with Open status.

Discussion:

In C++03 the following two programs are invalid:

1. >     #include <cmath>

   >     int main() {
   >       std::abs(0u);
   >     }

2. >     #include <cstdlib>

   >     int main() {
   >       std::abs(0u);
   >     }

because none of the `std::abs()` overloads is a best match.

In C++11 the additional "sufficient overload" rule from 26.8 [c.math] p11 (see also LWG 2086) can be read to be applicable to the `std::abs()` overloads as well, which can lead to the following possible conclusions:

1. The program

   >     #include <type_traits>
   >     #include <cmath>

   >     static_assert(std::is_same<decltype(std::abs(0u)), double>(), "Oops");

   >     int main() {
   >       std::abs(0u); // Calls std::abs(double)
   >     }

   is required to be well-formed, because of sub-bullet 2 ("[..] or an integer type [..]") of 26.8 [c.math] p11 (Note that the current resolution of LWG 2086 doesn't fix this problem).

2. Any translation unit including both `<cmath>` and `<cstdlib>` might be ill-formed because of two conflicting requirements for the return type of the overload `std::abs(int)`.

It seems to me that at least the second outcome is not intended, personally I think that both are unfortunate: In contrast to all other floating-point functions explicitly listed in sub-clause 26.8 [c.math], the `abs` overloads have a special and well-defined meaning for signed integers and thus have explicit overloads returning a signed integral type. I also believe that there is no problem accepting that `std::fabs(0u)` is well-defined with return type `double`, because the leading 'f' clearly signals that we have a floating point function here. But the expected return type of `std::abs(0u)` seems less than clear to me. A very reasonable answer could be that this has the same type as its argument type, alternatively it could be a reasonably chosen signed integer type, or a floating point type. It should also be noted, that the corresponding "generic type function" rule set from C99/C1x in 7.25 p2+3 is restricted to the floating-point functions from `<math.h>` and `<complex.h>`, so cannot be applied to the `abs` functions (but to the `fabs` functions!).

Selecting a signed integer return type for unsigned input values can also problematic: The directly corresponding signed integer type would give half of the possible argument values an implementation-defined result value. Choosing the first signed integer value that can represent all positive values would solve this problem for `unsigned int`, but there would be no clear answer for the input type `std::uintmax_t`.

Based on this it seems to me that the C++03 state in regard to unsigned integer values was the better situation, alerting the user that this code is ambigious at the moment (This might be change with different core-language rules as described in N3387).

[2013-04-20, Bristol]

Resolution: leave as new and bring it back in Chicago.

[2013-09 Chicago]

This issue also relates to LWG 2294

STL: these two issues should be bundled

Stefanus: do what Pete says, and add overloads for unsigned to return directly

STL: agree Consensus that this is an issue

Walter: motion to move to Open

STL: no wording for 2294

Stefanus: move to open and note the 2 issues are related and should be moved together

Stefanus: add and define unsigned versions of `abs()`

[2014-02-03 Howard comments]

Defining `abs()` for unsigned integers is a bad idea. Doing so would turn compile time errors into run time errors, especially in C++ where we have templates, and the types involved are not always apparent to the programmer at design time. For example, consider:

>     template <class Int>
>     Int
>     analyze(Int x, Int y)
>     {
>       // ...
>       if (std::abs(x - y) < threshold)
>       {
>         // ...
>       }
>       // ...
>     }

`std::abs(expr)` is often used to ask: Are these two numbers sufficiently close? When the assumption is that the two numbers are signed (either signed integral, or floating point), the logic is sound. But when the same logic is accidentally used with an arithmetic type not capable of representing negative numbers, and especially if unsigned overflow will silently happen, then the logic is no longer correct:

>     auto i = analyze(20u, 21u);  // Today a compile time error
>         // But with abs(unsigned) becomes a run time error

This is not idle speculation. Search the net for "`abs unsigned`" here or here.

In C++11, `chrono` `duration`s and `time_point`s are allowed to be based on unsigned integers. Taking the absolute value of the difference of two such `time_point`s would be easy to accidentally do (say in code templated on `time_point`s), and would certainly be a logic bug, caught at compile time unless we provide the error prone `abs(unsigned)`.

Proposed resolution:

This wording is relative to N3376.

1. Change 26.8 [c.math] p11 as indicated:

   > -11- Moreover, except for the `abs` functions, there shall be additional overloads sufficient to ensure:

   > […]

### 2195. Missing constructors for `match_results`

Section: 28.10 [re.results] Status: Open Submitter: Daniel Krügler Opened: 2012-10-06 Last modified: 2014-06-17

View all other issues in [re.results].

View all issues with Open status.

Discussion:

The requirement expressed in 28.10 [re.results] p2

> The class template `match_results` shall satisfy the requirements of an allocator-aware container and of a sequence container, as specified in 23.2.3 [sequence.reqmts], except that only operations defined for const-qualified sequence containers are supported.

can be read to require the existence of the described constructors from as well, but they do not exist in the synopsis.

The missing sequence constructors are:

>     match_results(initializer_list<value_type>);
>     match_results(size_type, const value_type&);
>     template<class InputIterator> match_results(InputIterator, InputIterator);

The missing allocator-aware container constructors are:

>     match_results(const match_results&, const Allocator&);
>     match_results(match_results&&, const Allocator&);

It should be clarified, whether (a) constructors are an exception of above mentioned operations or (b) whether at least some of them (like those accepting a `match_results` value and an allocator) should be added.

As visible in several places of the standard (including the core language), constructors seem usually to be considered as "operations" and they certainly can be invoked for const-qualified objects.

The below given proposed resolution applies only the minimum necessary fix, i.e. it excludes constructors from above requirement.

[2013-04-20, Bristol]

Check current implementations to see what they do and, possibly, write a paper.

[2013-09 Chicago]

Ask Daniel to update the proposed wording to include the allocator copy and move constructors.

[2014-01-18 Daniel changes proposed resolution]

Previous resolution from Daniel [SUPERSEDED]:

> 1. Change 28.10 [re.results] p2 as indicated:

>    > The class template `match_results` shall satisfy the requirements of an allocator-aware container and of a sequence container, as specified in 23.2.3 [sequence.reqmts], except that only operations defined for const-qualified sequence containers that are not constructors are supported.

Proposed resolution:

This wording is relative to N3936.

1. Change 28.10 [re.results] p4, class template `match_results` synopsis, as indicated:

   >     […]
   >     // 28.10.1, construct/copy/destroy:
   >     explicit match_results(const Allocator& a = Allocator());
   >     match_results(const match_results& m);
   >     match_results(const match_results& m, const Allocator& a);
   >     match_results(match_results&& m) noexcept;
   >     match_results(match_results&& m, const Allocator& a) noexcept;
   >     […]

2. Change 28.10.1 [re.results.const] as indicated: [Drafting note: Paragraph 6 as currently written, makes not much sense, because the `noexcept` does not allow any exception to propagate. Further-on, the allocator requirements do not allow for throwing move constructors. Deleting it seems to be near to editorial — end drafting note]

   >     match_results(const match_results& m);
   >     match_results(const match_results& m, const Allocator& a);

   > > -4- Effects: Constructs an object of class `match_results`, as a copy of `m`.

   >     match_results(match_results&& m) noexcept;
   >     match_results(match_results&& m, const Allocator& a) noexcept;

   > > -5- Effects: Move-constructs an object of class `match_results` from `m` satisfying the same postconditions as Table 142. Additionally For the first form, the stored `Allocator` value is move constructed from `m.get_allocator()`.

   > > -6- Throws: Nothing if the allocator's move constructor throws nothing.

### 2198. `max_load_factor(z)` makes no strong guarantees, but bans useful behavior

Section: 23.2.5 [unord.req] Status: Open Submitter: Alisdair Meredith Opened: 2012-10-09 Last modified: 2014-02-11

View other active issues in [unord.req].

View all other issues in [unord.req].

View all issues with Open status.

Discussion:

The user cannot specify a `max_load_factor` for their unordered container at construction, it must be supplied after the event, when the container is potentially not empty. The contract for this method is deliberately vague, not guaranteeing to use the value supplied by the user, and any value actually used will be used as a ceiling that the container will attempt to respect.

The only guarantee we have is that, if user requests a `max_load_factor` that is less than the current `load_factor`, then the operation will take constant time, thus outlawing an implementation that chooses to rehash and so preserve as a class invariant that `load_factor < max_load_factor`.

Reasonable options conforming to the standard include ignoring the user's request if the requested value is too low, or deferring the rehash to the next `insert` operation and allowing the container to have a strange state (wrt `max_load_factor`) until then - and there is still the question of rehashing if the next `insert` is for a duplicate key in a unique container.

Given the deliberate vagueness of the current wording, to support a range of reasonable (but not perfect) behaviors, it is not clear why the equally reasonable rehash to restore the constraint should be outlawed. It is not thought that this is a performance critical operation, where users will be repeatedly setting low load factors on populated containers, in a tight or (less unlikely) an instant response scenario.

[2013-03-15 Issues Teleconference]

Moved to Open.

Alisdair to provide wording.

Proposed resolution:

### 2199. unordered containers are required to have an initial max load factor of 1.0

Section: 23.2.5 [unord.req] Status: Open Submitter: Alisdair Meredith Opened: 2012-10-09 Last modified: 2014-02-11

View other active issues in [unord.req].

View all other issues in [unord.req].

View all issues with Open status.

Discussion:

The default constructor, allocator-aware constructor, and range-based constructors for the unordered containers do not offer a means to control the initial `max_load_factor`, so the standard mandates the value 1.0. This seems overly restrictive, as there is plenty of research suggesting a value between 0.5 and 1.0 is more often optimal for unique-key containers, and perhaps a slightly higher value might be appropriate for multi-containers.

Rather than guess at the appropriate `max_load_factor`, it seems reasonable that the standard should allow vendors to pick a value at their discretion, with perhaps a note of advice. It is less clear whether the default value should be implementation-defined or unspecified, given the ease of a user determining this by querying this attribute immediately after construction.

[2013-03-15 Issues Teleconference]

Moved to Open.

Alisdair to provide wording.

Marshall: It seems to me that what you really want is to be able to pass a max load factor in the constructor, but that's a different issue.

Alisdair agrees in principle, but concerned with adding yet more constructors to these classes.

Proposed resolution:

### 2201. Missing macro entries from C standard library

Section: C.4 [diff.library] Status: New Submitter: Kevin McCarty Opened: 2012-02-03 Last modified: 2014-03-02

View all other issues in [diff.library].

View all issues with New status.

Discussion:

It seems that in C.4 [diff.library], Table 150 the following macros from 18.3.3 [c.limits], Table 31 are missing:

>     LLONG_MIN
>     LLONG_MAX
>     ULLONG_MAX

In addition in C.4 [diff.library], Table 150 the following macros from 18.3.3 [c.limits], Table 32 are missing:

>     DECIMAL_DIG
>     FLT_EVAL_METHOD

Furtheron it seems that in C.4 [diff.library], Table 149/150 further macros are missing as well, e.g. `HUGE_VALF`, `INFINITY`, etc.

[2014-02 Issaquah:]

This is an issue, all of C has not been updated for C99, C99 functions are missing, whole section needs to be overhauled.

The issue needs to be updated for functions and other missing items and when that happens the issue title is wrong and needs to be adapted.

Proposed resolution:

### 2202. Missing allocator support by `async`

Section: 30.6.8 [futures.async] Status: Open Submitter: Detlef Vollmann Opened: 2012-10-19 Last modified: 2014-02-20

View all other issues in [futures.async].

View all issues with Open status.

Discussion:

`promise`, `packaged_task`, and `async` are the only places where a shared state is actually supposed to be allocated. Accordingly, `promise` and `packaged_task` are "allocator-aware". But function template `async` provides no way to provide an allocator.

[2013-09 Chicago]

Matt: deprecate async

Nico: read my paper

Alisdair: defer issues to wait for polymorphic allocators

Alisdair: defer, active topic of research Deferred

[2014-02-20 Re-open Deferred issues as Priority 4]

Proposed resolution:

### 2206. Inaccuracy in `initializer_list` constructor requirements

Section: 23.2.3 [sequence.reqmts], 23.2.4 [associative.reqmts], 23.2.5 [unord.req], 26.5.1.2 [rand.req.seedseq] Status: Open Submitter: Jeffrey Yasskin Opened: 2012-10-21 Last modified: 2014-02-11

View other active issues in [sequence.reqmts].

View all other issues in [sequence.reqmts].

View all issues with Open status.

Discussion:

In 23.2.3 [sequence.reqmts] p3, we have "`il` designates an object of type `initializer_list<value_type>`", and then several functions that take '`il`' as an argument. However, an expression like `{1, 2, 'a'}` is not an object of type `initializer_list<int>` unless it's used to initialize an explicitly-typed variable of that type. I believe we want:

>     std::vector<int> v;
>     v = {1, 2, 'a'};

to compile portably, so we should say something different when defining '`il`'. The same phrasing happens in 23.2.4 [associative.reqmts], 23.2.5 [unord.req], and 26.5.1.2 [rand.req.seedseq].

This may just be an editorial issue because the actual class synopses declare the functions to take `initializer_list<exact_type>`.

[2013-03-15 Issues Teleconference]

Moved to Open.

This is definitely not NAD

Should copy the suggested wording as the proposed resolution.

Proposed resolution:

### 2208. `std::reverse_iterator` should be a literal type

Section: 24.5.1 [reverse.iterators] Status: New Submitter: Jeffrey Yasskin Opened: 2012-10-30 Last modified: 2014-02-11

View all other issues in [reverse.iterators].

View all issues with New status.

Discussion:

`std::reverse_iterator::reverse_iterator(Iterator)` should be constexpr so that other constexpr functions can return `reverse_iterator`s. Of the other methods, the other constructors, `base()`, `operator+`, `operator-`, `operator[]`, and the non-member operators can probably also be `constexpr`.

`operator*` cannot be constexpr because it involves an assignment to a member variable. Discussion starting with c++std-lib-33282 indicated that it would be useful to make reverse_iterator a literal type despite this restriction on its use at compile time.

Proposed resolution:

### 2212. `tuple_size` for `const pair` request `<tuple>` header

Section: 20.2 [utility] Status: Tentatively Ready Submitter: Alisdair Meredith Opened: 2012-11-09 Last modified: 2014-05-02

View all other issues in [utility].

View all issues with Tentatively Ready status.

Discussion:

The `<utility>` header declares sufficient of the tuple API to specialize the necessary templates for `pair`, notably `tuple_size` and `tuple_element`. However, it does not make available the partial specializations that support cv-qualified template arguments, so while I can write the following after including only `<utility>`:

>     #include <utility>

>     using TestType = std::pair<int, int>;
>     static_assert(2 == std::tuple_size<TestType>(), "Pairs have two elements");
>     std::tuple_element<0, TestType>::type var{1};

the following may fail to compile unless I also include `<tuple>`:

>     #include <utility>

>     using TestType = const std::pair<int, int>;
>     static_assert(2 == std::tuple_size<TestType>(), "Pairs have two elements");
>     std::tuple_element<0, TestType>::type var{1};

Note, however, that the latter may compile with some standard library implementations but not others, leading to subtle portability issues.

[2013-03-15 Issues Teleconference]

Moved to Open.

Howard notes that we have the same issue with array, so any resolution should apply to that header too.

[2013-10-18 Daniel provides wording]

The suggested wording uses a similar approach as we already have in 24.7 [iterator.range] to ensure that the range access templates are available when at least one of an enumerated list of header files is included.

I also think that the restricted focus on `tuple_size` of this issue is too narrow and should be extended to the similar partial template specializations of `tuple_element` as well. Therefore the suggested wording ensures this as well.

[2014-03-27 Library reflector vote]

The issue has been identified as Tentatively Ready based on eight votes in favour.

Proposed resolution:

This wording is relative to N3936.

1. Change 20.4.2.5 [tuple.helper] as indicated:

   >     template <class T> class tuple_size<const T>;
   >     template <class T> class tuple_size<volatile T>;
   >     template <class T> class tuple_size<const volatile T>;

   > > -3- Let `TS` denote `tuple_size<T>` of the cv-unqualified type `T`. Then each of the three templates shall meet the `UnaryTypeTrait` requirements (20.10.1) with a `BaseCharacteristic` of

   > > >     integral_constant<size_t, TS::value>

   > > -?- In addition to being available via inclusion of the `<tuple>` header, each of the three templates are available when any of the headers `<array>` or `<utility>` are included.

   >     template <size_t I, class T> class tuple_element<I, const T>;
   >     template <size_t I, class T> class tuple_element<I, volatile T>;
   >     template <size_t I, class T> class tuple_element<I, const volatile T>;

   > > -?- Let `TE` denote `tuple_element<I, T>` of the cv-unqualified type `T`. Then each of the three templates shall meet the `TransformationTrait` requirements (20.10.1) with a member typedef `type` that names the following type:

   > > - for the first specialization, `add_const<TE::type>::type`,

   > > - for the second specialization, `add_volatile<TE::type>::type`, and

   > > - for the third specialization, `add_cv<TE::type>::type`.

   > > -?- In addition to being available via inclusion of the `<tuple>` header, each of the three templates are available when any of the headers `<array>` or `<utility>` are included.

### 2214. Clarify `basic_ios::init` call restrictions

Section: 27.5.5.2 [basic.ios.cons] Status: Open Submitter: Andrey Semashev Opened: 2012-11-09 Last modified: 2014-02-11

View all other issues in [basic.ios.cons].

View all issues with Open status.

Discussion:

There is an ambiguity in how `std::basic_ios::init` method (27.5.5.2 [basic.ios.cons]) can be used in the derived class. The Standard only specify the state of the `basic_ios` object after the call completes. However, in `basic_ios` default constructor description (27.5.5.2 [basic.ios.cons]) there is this sentence:

> Effects: Constructs an object of class `basic_ios` (27.5.3.7 [ios.base.cons]) leaving its member objects uninitialized. The object shall be initialized by calling `basic_ios::init` before its first use or before it is destroyed, whichever comes first; otherwise the behavior is undefined.

This restriction hints that `basic_ios::init` should be called exactly once before the object can be used or destroyed, because `basic_ios::init` may not know whether it was called before or not (i.e. whether its members are actually uninitialized or are initialized by the previous call to `basic_ios::init`). There is no such restriction in the `basic_ios::init` preconditions so it is not clear whether it is allowed to call `basic_ios::init` multiple times or not.

This problem has already affected publicly available implementations. For example, Microsoft Visual C++ STL introduces a memory leak if `basic_ios::init` is called multiple times, while GCC 4.7 and STLPort reinitialize the `basic_ios` object correctly without memory leak or any other undesired effects. There was a discussion of this issue on Boost developers mailing list, and there is a test case that reproduces the problem. The test case is actually a bug report for my Boost.Log library, which attempts to cache `basic_ostream`-derived objects internally to avoid expensive construction and destruction. My stream objects allowed resetting the stream buffer pointers the stream is attached to, without requiring to destroy and construct the stream.

My personal view of the problem and proposed resolution follows.

While apparently the intent of `basic_ios::init` is to provide a way to initialize `basic_ios` after default construction, I see no reason to forbid it from being called multiple times to reinitialize the stream. Furthermore, it is possible to implement a conforming `basic_ios` that does not have this restriction.

The quoted above section of the Standard that describes the effects of the default constructor is misleading. The Standard does not mandate any data members of `basic_ios` or `ios_base` (27.5.3 [ios.base]), which it derives from. This means that the implementation is allowed to use non-POD data members with default constructors that initialize the members with particular default values. For example, in the case of Microsoft Visual C++ STL the leaked memory is an `std::locale` instance that is dynamically allocated during `basic_ios::init`, a raw pointer to which is stored within ios_base. It is possible to store e.g. an `unique_ptr` instead of a raw pointer as a member of `ios_base`, the smart pointer will default initialize the underlying raw pointer on default construction and automatically destroy the allocated object upon being reset or destroyed, which would eliminate the leak and allow `basic_ios::init` to be called multiple times. This leads to conclusion that the default constructor of `basic_ios` cannot leave "its member objects uninitialized" but instead performs default initialization of the member objects, which would mean the same thing in case of POD types.

However, I feel that restricting `ios_base` and `basic_ios` members to non-POD types is not acceptable. Since multiple calls to `basic_ios::init` are not forbidden by the Standard, I propose to correct the `basic_ios` default constructor description so that it is allowed to destroy `basic_ios` object without calling `basic_ios::init`. This would imply that any raw members of `basic_ios` and `ios_base` should be initialized to values suitable for destruction (essentially, this means only initializing raw pointers to NULL). The new wording could look like this:

> Effects: Constructs an object of class `basic_ios` (27.5.3.7 [ios.base.cons]) initializing its member objects to unspecified state, only suitable for `basic_ios` destruction. The object shall be initialized by calling `basic_ios::init` before its first use; otherwise the behavior is undefined.

This would remove the hint that `basic_ios::init` must be called exactly once. Also, this would remove the requirement for `basic_ios::init` to be called at all before the destruction. This is also an important issue because the derived stream constructor may throw an exception before it manages to call `basic_ios::init` (for example, if the streambuf constructor throws), and in this case the `basic_ios` destructor has undefined behavior.

To my mind, the described modification is sufficient to resolve the issue. But to emphasize the possibility to call `basic_ios::init` multiple times, a remark or a footnote for `basic_ios::init` postconditions could be added to explicitly state the semantics of calling it multiple times. The note could read as follows:

> The function can be called multiple times during the object lifetime. Each subsequent call reinitializes the object to the described in postconditions initial state.

[2013-04-20, Bristol]

Alisdair: The current wording is unclear but the proposed resolution is wrong

Solution: Clarify that `init` must be called once and only once. Move then to review.

Proposed resolution:

This wording is relative to N3485.

1. Edit 27.5.5.2 [basic.ios.cons] as indicated:

   >     basic_ios();

   > > -2- Effects: Constructs an object of class `basic_ios` (27.5.3.7 [ios.base.cons]) leaving its member objects uninitialized initializing its member objects to unspecified state, only suitable for `basic_ios` destruction. The object shall be initialized by calling `basic_ios::init` before its first use or before it is destroyed, whichever comes first; otherwise the behavior is undefined.

   >     void init(basic_streambuf<charT,traits>* sb);

   > > Postconditions: The postconditions of this function are indicated in Table 128.

   > > -?- Remarks: The function can be called multiple times during the object lifetime. Each subsequent call reinitializes the object to the described in postconditions initial state.

### 2215. (unordered) associative container functors should be `CopyConstructible`

Section: 23.2.4 [associative.reqmts], 23.2.5 [unord.req] Status: Open Submitter: Alisdair Meredith Opened: 2012-11-14 Last modified: 2014-06-17

View other active issues in [associative.reqmts].

View all other issues in [associative.reqmts].

View all issues with Open status.

Discussion:

The requirements on the functors used to arrange elements in the various associative and unordered containers are given by a set of expressions in tables 102 — Associative container requirements, and 103 — Unordered associative container requirements. In keeping with Library convention these expressions make the minimal requirements necessary on their types. For example, we have the following 3 row extracts for the unordered containers:

Expression | Assertion/note pre-/post-condition
    X(n, hf, eq)
    X a(n, hf, eq)
| Requires: `hasher` and `key_equal` are `CopyConstructible`.
    X(n, hf)
    X a(n, hf)
| Requires: `hasher` is `CopyConstructible` and `key_equal` is `DefaultConstructible`.
    X(n)
    X a(n)
| Requires: `hasher` and `key_equal` are `DefaultConstructible`.

However, the signature for each class template requires that the functors must effectively be `CopyConstructible` for each of these expressions:

>     template <class Key,
>               class T,
>               class Hash  = hash<Key>,
>               class Pred  = std::equal_to<Key>,
>               class Allocator = std::allocator<std::pair<const Key, T> > >
>     class unordered_map
>     {
>       ...

>       // construct/destroy/copy
>       explicit unordered_map(size_type n = see below,
>                              const hasher& hf = hasher(),
>                              const key_equal& eql = key_equal(),
>                              const allocator_type& a = allocator_type());

>       ...
>     }

The letter of the standard can be honored as long as implementors recognize their freedom to split this one signature into multiple overloads, so that the documented default arguments (requiring a `CopyConstructible` functor) are not actually passed as default arguments.

As we look into the requirements for the copy constructor and copy-assignment operator, the requirements are even more vague, as the explicit requirements on the functors are not called out, other than saying that the functors are copied.

Must the functors be `CopyAssignable`? Or is `CopyConstructible` sufficient in this case? Do we require that the functors be `Swappable` so that the copy-swap idiom can be deployed here? Note that a type that is both `CopyConstructible` and `CopyAssignable` is still not guaranteed to be `Swappable` as the user may delete the `swap` function for their type in their own namespace, which would be found via ADL.

Some clean-up of the requirements table looks necessary, to at least document the assignment behavior. In addition, we should have clear guidance on whether these functors should always be `CopyConstructible`, as suggested by the class template definitions, or if the requirement tables are correct and we should explicitly split up the constructors in the (unordered) associative containers to no longer use default (function) arguments to obtain their defaulted functors.

I recommend the simplest solution would be to always require that the functors for (unordered) associative containers be `CopyConstructible`, above the requirements tables themselves, so that the issue need not be addressed within the tables. I suggest that the assignment operators for these containers add the requirement that the functors be `Swappable`, rather than forwarding the corresponding `Assignable` requirement.

[2013-03-15 Issues Teleconference]

Moved to Open.

Alisdair to propose wording.

[2014-06-08, Daniel comments]

The area of this issue partially overlaps what LWG 2227 addresses.

Proposed resolution:

### 2216. `regex_replace(basic_string)` allocator handling

Section: 28.11.4 [re.alg.replace] Status: New Submitter: Jeffrey Yasskin Opened: 2012-11-26 Last modified: 2014-02-11

View all other issues in [re.alg.replace].

View all issues with New status.

Discussion:

>     template <class traits, class charT, class ST, class SA>
>       basic_string<charT, ST, SA>
>       regex_replace(const basic_string<charT, ST, SA>& s,
>           const basic_regex<charT, traits>& e,
>           const charT* fmt,
>           regex_constants::match_flag_type flags =
>     	    regex_constants::match_default);

and friends are documented as

> Constructs an empty string result of type `basic_string<charT, ST, SA>` and calls `regex_replace(back_inserter(result), s.begin(), s.end(), e, fmt, flags)`.

This appears to require the result to have a default-constructed allocator, which isn't even possible for all allocator types. I suspect the allocator should be copied from 's' instead. Possibly there should be an additional defaulted argument to override the allocator of the result.

Proposed resolution:

### 2217. `operator==(sub_match, string)` slices on embedded `'\0'`s

Section: 28.9.2 [re.submatch.op] Status: Tentatively Ready Submitter: Jeffrey Yasskin Opened: 2012-11-26 Last modified: 2014-05-02

View all other issues in [re.submatch.op].

View all issues with Tentatively Ready status.

Discussion:

>     template <class BiIter, class ST, class SA>
>       bool operator==(
>         const basic_string<
>           typename iterator_traits<BiIter>::value_type, ST, SA>& lhs,
>         const sub_match<BiIter>& rhs);

is specified as:

> Returns: `rhs.compare(lhs.c_str()) == 0`.

This is odd because `sub_match::compare(basic_string)` is defined to honor embedded `'\0'` characters. This could allow a `sub_match` to `==` or `!=` a `std::string` unexpectedly.

[Daniel:]

This wording change was done intentionally as of LWG 1181, but the here mentioned slicing effect was not considered at that time. It seems best to use another overload of compare to fix this problem:

> Returns: `rhs.str().compare(0, rhs.length(), lhs.data(), lhs.size()) == 0`.

or

> Returns: `rhs.compare(sub_match<BiIter>::string_type(lhs.data(), lhs.size())) == 0`.

[2013-10-17: Daniel provides concrete wording]

The original wording was suggested to reduce the need to allocate memory during comparisons. The specification would be very much easier, if `sub_match` would provide an additional `compare` overload of the form:

>     int compare(const value_type* s, size_t n) const;

But given the fact that currently all of `basic_string`'s `compare` overloads are defined in terms of temporary string constructions, the following proposed wording does follow the same string-construction route as `basic_string` does (where needed to fix the embedded zeros issue) and to hope that existing implementations ignore to interpret this semantics in the literal sense.

I decided to use the second replacement form

>     Returns: rhs.compare(sub_match<BiIter>::string_type(lhs.data(), lhs.size())) == 0.

because it already reflects the existing style used in 28.9.2 [re.submatch.op] p31.

[2014-02-15 post-Issaquah session : move to Tentatively Ready]

Proposed resolution:

This wording is relative to N3691.

1. Change 28.9.2 [re.submatch.op] as indicated:

   >     template <class BiIter, class ST, class SA>
   >       bool operator==(
   >         const basic_string<
   >           typename iterator_traits<BiIter>::value_type, ST, SA>& lhs,
   >         const sub_match<BiIter>& rhs);

   > > -7- Returns: `rhs.compare(lhs.c_str()typename sub_match<BiIter>::string_type(lhs.data(), lhs.size())) == 0`.

   […]

   >     template <class BiIter, class ST, class SA>
   >       bool operator<(
   >         const basic_string<
   >           typename iterator_traits<BiIter>::value_type, ST, SA>& lhs,
   >         const sub_match<BiIter>& rhs);

   > > -9- Returns: `rhs.compare(lhs.c_str()typename sub_match<BiIter>::string_type(lhs.data(), lhs.size())) > 0`.

   […]

   >     template <class BiIter, class ST, class SA>
   >       bool operator==(const sub_match<BiIter>& lhs,
   >                       const basic_string<
   >                         typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);

   > > -13- Returns: `lhs.compare(rhs.c_str()typename sub_match<BiIter>::string_type(rhs.data(), rhs.size())) == 0`.

   […]

   >     template <class BiIter, class ST, class SA>
   >       bool operator<(const sub_match<BiIter>& lhs,
   >                      const basic_string<
   >                        typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);

   > > -15- Returns: `lhs.compare(rhs.c_str()typename sub_match<BiIter>::string_type(rhs.data(), rhs.size())) < 0`.

### 2218. Unclear how containers use `allocator_traits::construct()`

Section: 23.2.1 [container.requirements.general] Status: Open Submitter: Jonathan Wakely Opened: 2012-11-27 Last modified: 2014-02-11

View other active issues in [container.requirements.general].

View all other issues in [container.requirements.general].

View all issues with Open status.

Discussion:

Firstly, 23.2.1 [container.requirements.general]/7 says a container's allocator is used to obtain memory, but it isn't stated explicitly that the same allocator is used to construct and destroy elements, as opposed to a value-initialized allocator of the same type.

Secondly, 23.2.1 [container.requirements.general]/3 says elements "shall be constructed using the `allocator_traits<allocator_type>::construct` function and destroyed using the `allocator_traits<allocator_type>::destroy` function" and 23.2.1 [container.requirements.general]/13 defines `CopyInsertable` etc. in terms of an allocator `A` which is identical to the container's `allocator_type`.

The intent of making `construct()` and `destroy()` function templates was that containers would be permitted to use `allocator_traits<A>::construct()` instead of `allocator_traits<allocator_type>::construct()`, where `A` is `allocator_traits<allocator_type>::rebind_alloc<U>` for some other type `U`. This allows node-based containers to store an allocator of the right type for allocating nodes and to use the same object to construct elements in aligned storage within those nodes, avoiding rebinding and copying the stored allocator every time an element needs to be constructed.

It should be made clear that a possibly-rebound copy of the container's allocator is used for object construction.

[2013-03-15 Issues Teleconference]

Moved to Open.

Jonathan: point 2 in the proposed resolution is definitely needed.

Proposed resolution:

This wording is relative to N3485.

1. Edit 23.2.1 [container.requirements.general] paragraph 3:

   > For the components affected by this subclause that declare an `allocator_type`, objects stored in these components shall be constructed using the `allocator_traits<allocator_type>::rebind_alloc<U>::construct` function and destroyed using the `allocator_traits<allocator_type>::rebind_alloc<U>::destroy` function (20.7.8.2 [allocator.traits.members]), where `U` is either `allocator_type::value_type` or an internal type used by the container. These functions are called only for the container's element type, not for internal types used by the container. [ Note: This means, for example, that a node-based container might need to construct nodes containing aligned buffers and call construct to place the element into the buffer. — end note ]

2. Edit 23.2.1 [container.requirements.general] paragraph 7:

   > […] A copy of this allocator is used for any memory allocation and element construction performed, by these constructors and by all member functions, during the lifetime of each container object or until the allocator is replaced. […]

3. Edit 23.2.1 [container.requirements.general] paragraph 13:

   > […] Given an allocator type `A` and given a container type `X` having an `allocator_type` identical to `A` and a `value_type` identical to `T` and an `allocator_type` identical to `allocator_traits<A>::rebind_alloc<T>` and given an lvalue `m` of type `A`, a pointer `p` of type `T*`, an expression `v` of type (possibly `const`) `T`, and an rvalue `rv` of type `T`, the following terms are defined.

   > […]

   > [ Note: A container calls `allocator_traits<A>::construct(m, p, args)` to construct an element at `p` using `args`, with `m == get_allocator()`. The default `construct` in `std::allocator` will call `::new((void*)p) T(args)`, but specialized allocators may choose a different definition. — end note ]

### 2219. `INVOKE`-ing a pointer to member with a `reference_wrapper` as the object expression

Section: 20.9.2 [func.require] Status: Open Submitter: Jonathan Wakely Opened: 2012-11-28 Last modified: 2014-06-17

View other active issues in [func.require].

View all other issues in [func.require].

View all issues with Open status.

Discussion:

The standard currently requires this to be invalid:

>     #include <functional>

>     struct X { int i; } x;
>     auto f = &X::i;
>     auto t1 = std::ref(x);
>     int i = std::mem_fn(f)(t1);

The call expression on the last line is equivalent to `INVOKE(f, std::ref(x))` which according to 20.9.2 [func.require]p1 results in the invalid expression `(*t1).*f` because `reference_wrapper<X>` is neither an object of type `X` nor a reference to an object of type `X` nor a reference to an object of a type derived from `X`.

The same argument applies to pointers to member functions, and if they don't work with `INVOKE` it becomes harder to do all sorts of things such as:

> `call_once(o, &std::thread::join, std::ref(thr))`

or

> `async(&std::list<int>::sort, std::ref(list));`

The definition of `INVOKE` should be extended to handle reference wrappers.

[2013-03-15 Issues Teleconference]

Moved to Review.

The wording seems accurate, but verbose. If possible, we would like to define the kind of thing being specified so carefully as one of a number of potential language constructs in a single place. It is also possible that this clause is that single place.

[2013-04-18, Bristol]

Jonathan comments:

In the proposed resolution in the first bullet `(t1.*f)` is not valid if `t1` is a `reference_wrapper`, so we probably need a separate bullet to handle the `reference_wrapper` case.

[2014-02-14, Issaquah, Mike Spertus supplies wording]

Previous resolution from Jonathan [SUPERSEDED]:

> This wording is relative to N3485.

> 1. Edit 20.9.2 [func.require]:

>    > Define `INVOKE(f, t1, t2, ..., tN)` as follows:

>    > - `(t1.*f)(t2, ..., tN)` when `f` is a pointer to a member function of a class `T` and `t1` is an object of type `T` or a reference to an object of type `T` or a reference to an object of a type derived from `T` `U` or an object of type `reference_wrapper<U>` or a reference to an object of type `reference_wrapper<U>` where `U` is either the type `T` or a type derived from `T`;

>    > - `((*t1).*f)(t2, ..., tN)` when `f` is a pointer to a member function of a class `T` and `t1` is not one of the types described in the previous item;

>    > - `t1.*f` when `N == 1` and `f` is a pointer to member data of a class `T` and `t1` is an object of type `T` or a reference to an object of type `T` or a reference to an object of a type derived from `T` `U` or an object of type `reference_wrapper<U>` or a reference to an object of type `reference_wrapper<U>` where `U` is either the type `T` or a type derived from `T`;

>    > - `(*t1).*f` when `N == 1` and `f` is a pointer to member data of a class `T` and `t1` is not one of the types described in the previous item;

>    > - `f(t1, t2, ..., tN)` in all other cases.

Proposed resolution:

This wording is relative to N3936.

1. Edit 20.9.2 [func.require]:

   > Define `INVOKE(f, t1, t2, ..., tN)` as follows:

   > - `(t1.*f)(t2, ..., tN)` when `f` is a pointer to a member function of a class `T` and `t1` is an object of type `T` or a reference to an object of type `T` or a reference to an object of a type derived from `T`;

   > - `(t1.get().*f)(t2, ..., tN)` when `f` is a pointer to a member function of class `T` and `t1` is an object of type `reference_wrapper<U>` where `U` is either the type `T` or a type derived from `T`.

   > - `((*t1).*f)(t2, ..., tN)` when `f` is a pointer to a member function of a class `T` and `t1` is not one of the types described in the previous item;

   > - `t1.*f` when `N == 1` and `f` is a pointer to member data of a class `T` and `t1` is an object of type `T` or a reference to an object of type `T` or a reference to an object of a type derived from `T`;

   > - `t1.get().*f` when `N == 1` and `f` is a pointer to member data of a class `T` and `t1` is an object of type `reference_wrapper<U>` where `U` is either the type `T` or a type derived from `T`.

   > - `(*t1).*f` when `N == 1` and `f` is a pointer to member data of a class `T` and `t1` is not one of the types described in the previous item;

   > - `f(t1, t2, ..., tN)` in all other cases.

### 2220. Under-specification of `operator==` for `regex_token_iterator`

Section: 28.12.2.2 [re.tokiter.comp] Status: New Submitter: Pete Becker Opened: 2012-11-21 Last modified: 2014-02-11

View all issues with New status.

Discussion:

Consider the following example:

>     std::string str0("x");
>     std::regex rg0("a");
>     std::regex_token_iterator it0(str0.begin(), str0.end(), rg0, -1); // points at "x" in str0
>     std::string str1("x");
>     std::regex rg1("b");
>     std::regex_token_iterator it1(str1.begin(), str1.end(), rg1, -1); // points at "x" in str1

28.12.2.2 [re.tokiter.comp] p1 says that `it0.operator==(it1)` returns true "if `*this` and `right` are both suffix iterators and `suffix == right.suffix`"; both conditions are satisfied in this example. It does not say that they must both be iterators into the same sequence, nor does it say (as general iterator requirements do) that they must both be in the domain of `==` in order for the comparison to be meaningful. It's a simple statement: they're equal if the strings they point at compare equal. Given this being a valid comparison, the obtained result of "true" looks odd.

The problem is that for iterator values prior to the suffix iterator, equality means the same regular expression and the same matched sequence (both uses of "same" refer to identity, not equality); for the suffix iterator, equality means that the matched sequences compare equal.

Proposed resolution:

### 2221. No formatted output operator for `nullptr`

Section: 27.7.3 [output.streams] Status: New Submitter: Matt Austern Opened: 2012-12-07 Last modified: 2014-06-17

View all issues with New status.

Discussion:

When I write

>     std::cout << nullptr << std::endl;

I get a compilation error, "ambiguous overload for '`operator<<`' in '`std::cout << nullptr`'". As far as I can tell, the compiler is right to issue that error. There are inserters for `const void*`, `const char*`, `const signed char*`, and `const unsigned char*`, and none for `nullptr_t`, so the expression really is ambiguous.

Proposed wording:

The obvious library solution is to add a `nullptr_t` overload, which would be defined something like

>     template<class C, class T>
>     basic_ostream<C, T>& operator<<(basic_ostream<C, T>& os, nullptr_t)
>     {
>       return os << (void*) nullptr;
>     }

We might also consider addressing this at a core level: add a special-case language rule that addresses all cases where you write `f(nullptr)` and `f` is overloaded on multiple pointer types. (Perhaps a tiebreaker saying that `void*` is preferred in such cases.)

Proposed resolution:

### 2223. `shrink_to_fit` effect on iterator validity

Section: 23.3.6.3 [vector.capacity] Status: Open Submitter: Juan Soulie Opened: 2012-12-17 Last modified: 2014-05-02

View other active issues in [vector.capacity].

View all other issues in [vector.capacity].

View all issues with Open status.

Discussion:

After the additions by 2033, it appears clear that the intended effect includes a reallocation and thus the potential effect on iterators should be explicitly added to the text in order to not contradict 23.2.1 [container.requirements.general]/11, or at the very least, explicitly state that a reallocation may happen.

Taking consistency with "reserve" into consideration, I propose:

- that the current "Remarks" are made its "Effect" instead, inserting "Reallocation happens at this point if and only if the function effectively reduces the capacity." after the note on non-bindingness.

- adding a "Remarks" paragraph, similar to that of reserve: "Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence."

BTW, while we are at it, I believe the effect on iterators should also be explicitly stated in the other instance a reallocation may happen: 23.3.6.5 [vector.modifiers]/1 — even if obvious, it only contradicts 23.2.1 [container.requirements.general]/11 implicitly.

I propose to also insert "Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence." at the appropriate location in its "Remarks".

[2012-12-19: Jonathan Wakely comments]

The described problem also affects `std::basic_string` and `std::deque`.

[2013-03-15 Issues Teleconference]

Moved to Review.

[2013-04-18, Bristol]

Daniel extends the P/R.

Rationale:

The wording in 21.4.4 [string.capacity] combined with 21.4.1 [string.require] seems to say the necessary things. We cannot impose all requirements as we do for `vector`, because we want to allow the short-string-optimization.

[2014-02-15 post-Issaquah session]

STL: I think that `shrink_to_fit` should be a no-op when called twice.

STL: Do we ever define reallocation for `deque`? Nope, all mentions of "reallocation" are in `vector`. We define what it means in `vector::reserve()`, but not for `deque`.

STL: Oh duh, they define reallocate in the PR. But I think we can do better here.

STL: Optimally, deque shrinking just allocates a new map of pointers, and drops empty blocks, but preserves pointers/references to elements.

Alisdair: That's like unordered containers, invalidating only iterators.

Pablo: It doesn't make sense to reduce `capacity()` to `size()`, because `deque` doesn't have capacity!

STL: For `vector`, "effectively reduces the capacity" is unnecessary, the capacity there is observable.

STL: There is a strong reason to provide an optimal shrink to fit for `deque`, since only the library implementer can do this.

STL: The other thing I don't like the repeated definition of reallocation for `vector`, we define it once and use it in a bunch of places. At most we can lift it up to the `vector` synopsis.

STL: I'll write new wording.

Proposed resolution:

This wording is relative to N3485.

1. Keep 21.4.4 [string.capacity] around p14 unchanged, because we don't speak about reallocations and we give the strong exception guarantee in 21.4.1 [string.require] (Invalidation specification also at that place):

   >     void shrink_to_fit();

   > -14- Remarks: `shrink_to_fit` is a non-binding request to reduce `capacity()` to `size()`. [Note: The request is non-binding to allow latitude for implementation-specific optimizations. — end note ].

2. Edit 23.3.3.3 [deque.capacity] around p7 as indicated:

   >     void shrink_to_fit();

   > -5- Requires: `T` shall be `MoveInsertable` into `*this`.

   > -?- Effects: `shrink_to_fit` is a non-binding request to reduce `capacity()` to `size()`. [Note: The request is non-binding to allow latitude for implementation-specific optimizations. — end note ] Reallocation happens at this point if and only if the function effectively reduces the capacity. If an exception is thrown other than by the move constructor of a non-`CopyInsertable` `T` there are no effects.

   > -6- Complexity: Linear in the size of the sequence.

   > -7- Remarks: `shrink_to_fit` is a non-binding request to reduce `capacity()` to `size()`. [Note: The request is non-binding to allow latitude for implementation-specific optimizations. — end note ] If an exception is thrown other than by the move constructor of a non-`CopyInsertable` `T` there are no effects.Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence.

3. Edit 23.3.6.3 [vector.capacity] around p7 as indicated:

   >     void shrink_to_fit();

   > -7- Requires: `T` shall be `MoveInsertable` into `*this`.

   > -?- Effects: `shrink_to_fit` is a non-binding request to reduce `capacity()` to `size()`. [Note: The request is non-binding to allow latitude for implementation-specific optimizations. — end note ] Reallocation happens at this point if and only if the function effectively reduces the capacity. If an exception is thrown other than by the move constructor of a non-`CopyInsertable` `T` there are no effects.

   > -8- Complexity: Linear in the size of the sequence.

   > -9- Remarks: `shrink_to_fit` is a non-binding request to reduce `capacity()` to `size()`. [Note: The request is non-binding to allow latitude for implementation-specific optimizations. — end note ] If an exception is thrown other than by the move constructor of a non-`CopyInsertable` `T` there are no effects.Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence.

4. Edit 23.3.6.5 [vector.modifiers] p1 as indicated:

   >     iterator insert(const_iterator position, const T& x);
   >     iterator insert(const_iterator position, T&& x);
   >     iterator insert(const_iterator position, size_type n, const T& x);
   >     template <class InputIterator>
   >     iterator insert(const_iterator position, InputIterator first, InputIterator last);
   >     iterator insert(const_iterator position, initializer_list<T>);
   >     template <class... Args> void emplace_back(Args&&... args);
   >     template <class... Args> iterator emplace(const_iterator position, Args&&... args);
   >     void push_back(const T& x);
   >     void push_back(T&& x);

   > -1- Remarks: Causes reallocation if the new size is greater than the old capacity. Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. If no reallocation happens, all the iterators and references before the insertion point remain valid. If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move assignment operator of `T` or by any `InputIterator` operation there are no effects. If an exception is thrown by the move constructor of a non-`CopyInsertable` `T`, the effects are unspecified.

### 2224. Ambiguous status of access to non-live objects

Section: 17.6.4.10 [res.on.objects] Status: Open Submitter: Geoffrey Romer Opened: 2012-12-17 Last modified: 2014-02-11

View all other issues in [res.on.objects].

View all issues with Open status.

Discussion:

The standard currently does not discuss when library objects may be accessed, except in a non-normative note pertaining to synchronization in [res.on.objects], leaving it ambiguous whether single-threaded code can access a library object during its construction or destruction. For example, there is a reasonable question as to what happens if the deleter supplied to a `unique_ptr` transitively accesses the `unique_ptr` itself during `unique_ptr`'s destruction; a straightforward reading suggests that this is permitted, and that the deleter will see the `unique_ptr` still holding the originally stored pointer, but consensus on the LWG reflector indicates this was not the intent (see discussion beginning with c++std-lib-33362).

[2013-03-15 Issues Teleconference]

Moved to Open.

Geoffrey will provide an example that clearly highlights the issue.

[2013-03-19 Geoffrey provides revised resolution and an example]

I contend that the most straightforward reading of the current standard requires the following example code to print "good" (because `~unique_ptr` is not specified to modify the state of the internal pointer), but the consensus on the reflector was that its behavior should be undefined.

This example also shows that, contrary to a comment in the telecon, the PR is not tautological. 12.7 [class.cdtor]/p4 explicitly permits member function calls during destruction, so the behavior of this code is well-defined as far as the core language is concerned, despite the fact that it accesses a library object after the end of the object's lifetime. If we want this code to have undefined behavior, we need to specify that at the library level.

>     #include <memory>
>     #include <iostream>

>     class A;

>     struct B {
>      std::unique_ptr<A> a;
>     };

>     struct A {
>      B* b;
>      ~A() {
>        if (b->a.get() == this) {
>          std::cout << "good" << std::endl;
>        }
>      }
>     };

>     int main() {
>      B b;
>      b.a.reset(new A);
>      b.a->b = &b;
>     }

Previous resolution:

> 1. Change the title of sub-clause 17.6.4.10 [res.on.objects] as indicated:

>    Shared objects and the library Library object access [res.on.objects]

> 2. Edit 17.6.4.10 [res.on.objects] p2 as indicated:

>    -2- [Note: In particular, the program is required to ensure that completion of the constructor of any object of a class type defined in the standard library happens before any other member function invocation on that object and, unless otherwise specified, to ensure that completion of any member function invocation other than destruction on such an object happens before destruction of that object. This applies even to objects such as mutexes intended for thread synchronization. — end note] If an object of a standard library type is accessed outside of the object's lifetime (3.8 [basic.life]), the behavior is undefined unless otherwise specified.

Proposed resolution:

This wording is relative to N3485.

1. Change the title of sub-clause 17.6.4.10 [res.on.objects] as indicated:

   Shared objects and the library Library object access [res.on.objects]

2. Edit 17.6.4.10 [res.on.objects] p2 as indicated: [Editorial remark: The motivation, is to be more precise about the meaning of "outside the object's lifetime" in the presence of threads — end editorial remark]

   -2- [Note: In particular, the program is required to ensure that completion of the constructor of any object of a class type defined in the standard library happens before any other member function invocation on that object and, unless otherwise specified, to ensure that completion of any member function invocation other than destruction on such an object happens before destruction of that object. This applies even to objects such as mutexes intended for thread synchronization. — end note] If an object of a standard library type is accessed, and the beginning of the object's lifetime (3.8 [basic.life]) does not happen before the access, or the access does not happen before the end of the object's lifetime, the behavior is undefined unless otherwise specified.

### 2227. Stateful comparison objects in associative containers

Section: 23.2.4 [associative.reqmts] Status: Open Submitter: Juan Soulie Opened: 2012-12-19 Last modified: 2014-02-11

View other active issues in [associative.reqmts].

View all other issues in [associative.reqmts].

View all issues with Open status.

Discussion:

Table 102 in 23.2.4 [associative.reqmts]/8 states on expression `a.key_comp()` that it "returns the comparison object out of which a was constructed". At the same time, 23.2.1 [container.requirements.general]/8 states (starting in the third line) that "...Any `Compare`, `Pred`, or `Hash` objects belonging to `a` and `b` shall be swappable and shall be exchanged by unqualified calls to non-member swap...". This is problematic for any compliant implementation, since once swapped the container cannot return the comparison object out of which it was constructed unless incurring in storing an otherwise needless object.

The simple solution is to correct that statement in Table 102, but I believe this is part of a larger problem of underspecified behavior: The new standard has made an effort in regards to allocators and now fully specifies what happens to stateful allocator objects. It has even specified what happens to stateful `hasher` and `key_equal` members of unordered containers (they propagate), but it says nothing about stateful comparison objects of (ordered) associative containers, except for the statement in 23.2.1 [container.requirements.general]/8 referred above and only related to `swap`.

For example, it is unclear to me what is specified to happen on an assignment: should the comparison object be copied/moved along with the elements, or should the left-hand side object keep its own? Maybe this has been intentionally left unspecified with the purpose of compatibility with C++98, which I understand it specified that comparison objects were kept for the entire life of the container (like allocators) — an unfortunate choice. But anyway, the segment of 23.2.1 [container.requirements.general] quoted above seems to break any possible backwards compatibility with C++98 in this regard.

Therefore, taking into consideration consistency with how this is dealed with for unordered associative containers, I propose that Table 102 is modified as follows:

- The row for expression `a.key_comp()` is changed so that its "assertion/note pre-/post-condition" reads "Returns `a`'s comparison object."

- A new row is added at the appropriate location (which I believe would be after "X(il)" row), with:

  > Table 102 — Associative container requirements (in addition to container)
  > Expression | Return type | Assertion/note pre-/post-condition | Complexity
  > --- | --- | --- | ---
  > `X(b) X a(b)` | `X` | Copy constructor. In addition to the requirements of Table 96, copies the comparison object. | Linear in `b.size()`
  > `a = b` | `X&` | Copy assignment operator. In addition to the requirements of Table 96, copies the comparison object. | Linear in `a.size()` and `b.size()`

[2013-03-15 Issues Teleconference]

Moved to Review.

[2013-04-18, Bristol]

STL: can't believe we don't specify this already. this is totally necessary

Alisdair: how does it do this? copy construction? assignment?

ALso need it for move.

STL: we already specify this for constructing from a comparator, not during copy construction though.

Jonathan: don't like wording, should say "`key_compare` is `CopyConstructible`. Uses `b.key_comp()` as a comparison object."

STL: we get it right for unordered!

Jonathan: can't wordsmith this now, but I think implementations do the right thing.

Alisdair: not sure what right thing is for moves. also we say nothing about propagating allocators to functors.

Moved to Open.

Proposed resolution:

This wording is relative to N3485.

1. Change Table 102 as indicated:

   > Table 102 — Associative container requirements (in addition to container)
   > Expression | Return type | Assertion/note pre-/post-condition | Complexity
   > --- | --- | --- | ---
   > `…`
   > `X(il)` | `` | Same as `X(il.begin(), il.end())`. | same as `X(il.begin(), il.end())`.
   > `X(b) X a(b)` | `` | Copy constructor. In addition to the requirements of Table 96, copies the comparison object. | Linear in `b.size()`
   > `a = b` | `X&` | Copy assignment operator. In addition to the requirements of Table 96, copies the comparison object. | Linear in `a.size()` and `b.size()`
   > `…`
   > `a.key_comp()` | `X::key_compare` | r Returns the `a`'s comparison object out of which a was constructed. | constant

### 2228. Missing SFINAE rule in `unique_ptr` templated assignment

Section: 20.8.1.2.3 [unique.ptr.single.asgn] Status: Review Submitter: Geoffrey Romer Opened: 2012-12-20 Last modified: 2014-02-11

View all other issues in [unique.ptr.single.asgn].

View all issues with Review status.

Discussion:

20.8.1.2.3 [unique.ptr.single.asgn]/5 permits `unique_ptr`'s templated assignment operator to participate in overload resolution even when incompatibilities between `D` and `E` will render the result ill-formed, but the corresponding templated copy constructor is removed from the overload set in those situations (see the third bullet point of 20.8.1.2.1 [unique.ptr.single.ctor]/19). This asymmetry is confusing, and presumably unintended; it may lead to situations where constructing one `unique_ptr` from another is well-formed, but assigning from the same `unique_ptr` would be ill-formed.

There is a slight coupling between this and LWG 2118, in that my PR for LWG 2118 incorporates equivalent wording in the specification of the templated assignment operator for the array specialization; the two PRs are logically independent, but if my PR for 2118 is accepted but the above PR is not, the discrepancy between the base template and the specialization could be confusing.

[2013-03-15 Issues Teleconference]

Moved to Review.

The wording looks good, but we want a little more time than the telecon permits to be truly comfortable. We expect this issue to resolve fairly easily in Bristol.

Proposed resolution:

This wording is relative to N3485.

1. Revise 20.8.1.2.3 [unique.ptr.single.asgn] p5 as follows:

   >     template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;

   > > -4- Requires: If `E` is not a reference type, assignment of the deleter from an rvalue of type `E` shall be well-formed and shall not throw an exception. Otherwise, `E` is a reference type and assignment of the deleter from an lvalue of type `E` shall be well-formed and shall not throw an exception.

   > > -5- Remarks: This operator shall not participate in overload resolution unless:

   > > - `unique_ptr<U, E>::pointer` is implicitly convertible to `pointer` and

   > > - `U` is not an array type., and

   > > - either `D` is a reference type and `E` is the same type as `D`, or `D` is not a reference type and `E` is implicitly convertible to `D`.

   > > -6- Effects: Transfers ownership from `u` to `*this` as if by calling `reset(u.release())` followed by an assignment from `std::forward<E>(u.get_deleter())`.

   > > -7- Returns: `*this`.

### 2230. "see below" for initializer-list constructors of unordered containers

Section: 23.5 [unord] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2013-01-06 Last modified: 2014-05-23

View all other issues in [unord].

View all issues with Tentatively Ready status.

Discussion:

The `unordered_map` class definition in 23.5.4.1 [unord.map.overview] declares an initializer-list constructor that says "see below":

>     unordered_map(initializer_list<value_type>,
>         size_type = see below,
>         const hasher& hf = hasher(),
>         const key_equal& eql = key_equal(),
>         const allocator_type& a = allocator_type());

But that constructor isn't defined below. The same problem exists for the other unordered associative containers.

[2013-09 Chicago]

STL: ordered are also missing declarations, but issue is forthcoming

Walter: how does adding a signature address issue? — nevermind

Jayson: in his wording, isn't he just dropping the `size_type`?

Walter: partial fix is to introduce the name

Stefanus: explanation of requiring name because of n buckets

STL: solution for his issue satisfies both ordered and unordered and is simplier than provided wording

STL: patches general table instead

STL: proposes adding extra rows instead of extra declarations

Stefanus: clarify `n` in the synopsis

Walter: general rule, name is optional in declaration

Stefanus: how to proceed

Walter: significant overlap with forthcoming issue, suggestion to defer

[2014-02-20 Re-open Deferred issues as Priority 4]

[2014-03-27 Jonathan improves proposed wording]

[2014-05-20 STL and Jonathan communicate]

STL: With 2322 resolved, is there anything left for this issue to fix?

Jonathan: The synopsis still says "see below" and it's not immediately clear that "see below" means "see the definition of a different constructor, which defines the behaviour of this one due to a table defined much earlier".

[2014-05-23 Library reflector vote]

The issue has been identified as Tentatively Ready based on five votes in favour.

Proposed resolution:

This wording is relative to N3936.

1. Edit 23.5.4.1 [unord.map.overview], class template `unordered_map` synopsis, as follows:

   >     […]
   >     unordered_map(initializer_list<value_type> il,
   >       size_type n = see below,
   >       const hasher& hf = hasher(),
   >       const key_equal& eql = key_equal(),
   >       const allocator_type& a = allocator_type());
   >     […]

2. Edit 23.5.4.2 [unord.map.cnstr] as follows:

   >     template <class InputIterator>
   >     unordered_map(InputIterator f, InputIterator l,
   >       size_type n = see below,
   >       const hasher& hf = hasher(),
   >       const key_equal& eql = key_equal(),
   >       const allocator_type& a = allocator_type());
   >     unordered_map(initializer_list<value_type> il,
   >       size_type n = see below,
   >       const hasher& hf = hasher(),
   >       const key_equal& eql = key_equal(),
   >       const allocator_type& a = allocator_type());

   > > -3- Effects: Constructs an empty `unordered_map` using the specified hash function, key equality function, and allocator, and using at least `n` buckets. If `n` is not provided, the number of buckets is implementation-defined. Then inserts elements from the range `[f, l)` for the first form, or from the range `[il.begin(), il.end())` for the second form. `max_load_factor()` returns `1.0`.

3. Edit 23.5.5.1 [unord.multimap.overview], class template `unordered_multimap` synopsis, as follows:

   >     […]
   >     unordered_multimap(initializer_list<value_type> il,
   >       size_type n = see below,
   >       const hasher& hf = hasher(),
   >       const key_equal& eql = key_equal(),
   >       const allocator_type& a = allocator_type());
   >     […]

4. Edit 23.5.5.2 [unord.multimap.cnstr] as follows:

   >     template <class InputIterator>
   >     unordered_multimap(InputIterator f, InputIterator l,
   >       size_type n = see below,
   >       const hasher& hf = hasher(),
   >       const key_equal& eql = key_equal(),
   >       const allocator_type& a = allocator_type());
   >     unordered_multimap(initializer_list<value_type> il,
   >       size_type n = see below,
   >       const hasher& hf = hasher(),
   >       const key_equal& eql = key_equal(),
   >       const allocator_type& a = allocator_type());

   > > -3- Effects: Constructs an empty `unordered_multimap` using the specified hash function, key equality function, and allocator, and using at least `n` buckets. If `n` is not provided, the number of buckets is implementation-defined. Then inserts elements from the range `[f, l)` for the first form, or from the range `[il.begin(), il.end())` for the second form. `max_load_factor()` returns `1.0`.

5. Edit 23.5.6.1 [unord.set.overview], class template `unordered_set` synopsis, as follows:

   >     […]
   >     unordered_set(initializer_list<value_type> il,
   >       size_type n = see below,
   >       const hasher& hf = hasher(),
   >       const key_equal& eql = key_equal(),
   >       const allocator_type& a = allocator_type());
   >     […]

6. Edit 23.5.6.2 [unord.set.cnstr] as follows:

   >     template <class InputIterator>
   >     unordered_set(InputIterator f, InputIterator l,
   >       size_type n = see below,
   >       const hasher& hf = hasher(),
   >       const key_equal& eql = key_equal(),
   >       const allocator_type& a = allocator_type());
   >     unordered_set(initializer_list<value_type> il,
   >       size_type n = see below,
   >       const hasher& hf = hasher(),
   >       const key_equal& eql = key_equal(),
   >       const allocator_type& a = allocator_type());

   > > -3- Effects: Constructs an empty `unordered_set` using the specified hash function, key equality function, and allocator, and using at least `n` buckets. If `n` is not provided, the number of buckets is implementation-defined. Then inserts elements from the range `[f, l)` for the first form, or from the range `[il.begin(), il.end())` for the second form. `max_load_factor()` returns `1.0`.

7. Edit 23.5.7.1 [unord.multiset.overview], class template `unordered_multiset` synopsis, as follows:

   >     […]
   >     unordered_multiset(initializer_list<value_type> il,
   >       size_type n = see below,
   >       const hasher& hf = hasher(),
   >       const key_equal& eql = key_equal(),
   >       const allocator_type& a = allocator_type());
   >     […]

8. Edit 23.5.7.2 [unord.multiset.cnstr] as follows:

   >     template <class InputIterator>
   >     unordered_multiset(InputIterator f, InputIterator l,
   >       size_type n = see below,
   >       const hasher& hf = hasher(),
   >       const key_equal& eql = key_equal(),
   >       const allocator_type& a = allocator_type());
   >     unordered_multiset(initializer_list<value_type> il,
   >       size_type n = see below,
   >       const hasher& hf = hasher(),
   >       const key_equal& eql = key_equal(),
   >       const allocator_type& a = allocator_type());

   > > -3- Effects: Constructs an empty `unordered_multiset` using the specified hash function, key equality function, and allocator, and using at least `n` buckets. If `n` is not provided, the number of buckets is implementation-defined. Then inserts elements from the range `[f, l)` for the first form, or from the range `[il.begin(), il.end())` for the second form. `max_load_factor()` returns `1.0`.

### 2233. `bad_function_call::what()` unhelpful

Section: 20.9.11.1 [func.wrap.badcall] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2013-01-05 Last modified: 2014-05-02

View all issues with Tentatively Ready status.

Discussion:

A strict reading of the standard implies `std::bad_function_call{}.what()` returns the same string as `std::exception{}.what()` which doesn't help to know what happened if you catch an exception by reference to `std::exception`.

For consistency with `bad_weak_ptr::what()` it should return `"bad_function_call"`.

See c++std-lib-33515 for other details.

There was a considerable support on the reflector to instead change the specification of both `bad_weak_ptr::what()` and `bad_function_call::what()` to return an implementation-defined string instead.

[2013-03-15 Issues Teleconference]

Moved to Open.

Consensus that we want consistency in how this is treated. Less consensus on what the common direction should be.

Alisdair to provide wording proposing that all string literals held by standard exception objects are either unspecified, or implmentation defined.

[2014-02-15 Issauqah]

STL: I think it should be an implementation-defined NTBS, same on `bad_weak_ptr`. I will write a PR.

[2014-03-27, STL provides improved wording]

The new wording reflects better the general agreement of the committee, see also issue 2376 for similar wording.

[2014-03-28 Library reflector vote]

The issue has been identified as Tentatively Ready based on five votes in favour.

Proposed resolution:

This wording is relative to N3936.

1. Edit 20.9.11.1.1 [func.wrap.badcall.const]:

   >     bad_function_call() noexcept;

   > > -1- Effects: constructs a `bad_function_call object`.

   > > -?- Postconditions: `what()` returns an implementation-defined NTBS.

### 2234. `assert()` should allow usage in constant expressions

Section: 19.3 [assertions] Status: Open Submitter: Daniel Krügler Opened: 2013-01-12 Last modified: 2014-06-17

View other active issues in [assertions].

View all other issues in [assertions].

View all issues with Open status.

Discussion:

It is unclear from the current specification whether `assert()` expressions can be used in (potential) constant expressions. As an example consider the implementation of a `constexpr` function:

>     #include <cassert>

>     template<class T, unsigned N>
>     struct array {
>       T data[N];
>       constexpr const T& operator[](unsigned i) const {
>         return assert(i < N), data[i];
>       }
>     };

>     int main() {
>       constexpr array<int, 3> ai = {1, 2, 3};
>       constexpr int i = ai[0];
>       int j = ai[0];
>       // constexpr int k = ai[5];
>     }

The first question is whether this program is guaranteed well-formed? A second question is whether is would guaranteed to be ill-formed, if we uncomment the last code line in `main()`?

The wording in 19.3 [assertions] doesn't add anything significant to the C99 wording. From the C99 specification (7.2 p1 and 7.2.1.1 p2) we get already some valuable guarantees:

- The expression `assert(e)` is a `void` expression for all expressions `e` independent of the definition of `NDEBUG`.

- If `NDEBUG` is defined, `assert(e)` is equivalent to the expression `void()` (or anything that cannot be distinguished from that).

The current wording does not yet guarantee that `assert` expressions can be used in constant expressions, but all tested implementations (gcc, MSVC) would already support this use-case. It seems to me that this should be possible without giving `assert` a special meaning for the core language.

As a related comment it should be added, that there is a core language proposal that intents to relax some current constraints for `constexpr` functions and `literal` types. The most interesting one (making `void` a literal types and allowing for expression-statements) would simplify the motivating example implementation of `operator[]` to:

>     constexpr const T& operator[](unsigned i) const {
>       assert(i < N);
>       return data[i];
>     };

[2013-03-15 Issues Teleconference]

Moved to Open.

We are still gaining experience with `constexpr` as a language feature, and there may be work in Evolution that would help address some of these concerns. Defer discussion until we have a group familiar with any evolutionary direction.

[2014-06-08, Daniel comments and suggests wording]

After approval of N3652, `void` is now a literal type and `constexpr` functions can contain multiple statements, so this makes the guarantee that `assert` expressions are per-se `constexpr`-friendly even more relevant. A possible wording form could be along the lines of:

> For every core constant expression e of scalar type that evaluates to `true` after being contextually converted to `bool`, the expression `assert(e)` shall be a prvalue core constant expression of type `void`.

Richard Smith pointed out some weaknesses of this wording form, for example it would not guarantee to require the following example to work:

>     constexpr void check(bool b) { assert(b); }

because `b` is not a core constant expression in this context.

He suggested improvements that lead to the wording form presented below (any defects mine).

Proposed resolution:

This wording is relative to N3936.

1. Introduce the following new definition to the existing list in 17.3 [definitions]: [Drafting note: If LWG 2296 is accepted before this issue, the accepted wording for the new definition should be used instead — end drafting note]

   > constant subexpression [defns.const.subexpr]

   > an expression whose evaluation as subexpression of a conditional-expression CE (5.16 [expr.cond]) would not prevent CE from being a core constant expression (5.19 [expr.const]).

2. Insert a new paragraph following 19.3 [assertions] p1 as indicated:

   > -?- An expression `assert(E)` is a constant subexpression ( [defns.const.subexpr]), if either

   > - `NDEBUG` is defined at the point where `assert(E)` appears, or

   > - `E` contextually converted to `bool` (4 [conv]), is a constant subexpression that evaluates to the value `true`.

### 2236. `kill_dependency` unconditionally noexcept

Section: 29.2 [atomics.syn], 29.3 [atomics.order] Status: New Submitter: Daniel Krügler Opened: 2013-01-19 Last modified: 2013-10-15

View all other issues in [atomics.syn].

View all issues with New status.

Discussion:

The "magic" `kill_dependency` function is a function without any constraints on the template parameter `T` and is specified as

>     template <class T>
>     T kill_dependency(T y) noexcept;

> > -14- Effects: The argument does not carry a dependency to the return value (1.10).

> > -15- Returns: `y`.

I wonder whether the unconditional noexcept is really intended here: Assume we have some type `U` that has a potentially throwing move constructor (or it has a potentially throwing copy constructor and no move constructor), for any "normal" function template with the same signature and the same effects (modulo the dependency magic) this would mean that it cannot safely be declared noexcept because of the return statement being part of the complete function call affected by noexcept (The by-value function argument is irrelevant in this context). In other words it seems that a function call such as

>     struct S {
>       ...
>       S(const S& r) { if(some condition) throw Something(); }
>       ...
>     };

>     int main() {
>       S s1 = ...;
>       S s2 = std::kill_dependency(s1);
>     }

would be required to call `std::terminate` if the copy constructor of `S` throws during the return of `std::kill_dependency`.

To require copy elision for this already magic function would look like a low-hanging fruit to solve this problem, but this case is not covered by current copy elision rules see 12.8 p31 b1:

"— in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function's return value".

Some options come into my mind:

1. Make the exception-specification a constrained one in regard via `std::is_nothrow_move_constructible`:

   >     template <class T>
   >     T kill_dependency(T y) noexcept(see below);

   This is similar to the approach taken for function templates such as std::swap.

2. Use perfect forwarding (This needs further wording to correct the effects):

   >     template <class T>
   >     T&& kill_dependency(T&& y) noexcept;

3. Impose constraints on the template arguments in regard to throwing exceptions while copying/moving.

4. Keep the state as it is but possibly add a note about a call of `std::terminate` in above scenario.

A second problem is that the current wording is not clear whether it is well-defined to call the function with types that are reference types, such as in the following example:

>     #include <atomic>

>     int main()
>     {
>       int a = 12;
>       int& b = std::kill_dependency<int&>(a);
>     }

It is unclear what kind of dependency is killed here. This is presumably a core language problem, but could affect the possible resolutions of the problem.

Proposed resolution:

### 2237. `<cuchar>` macros

Section: 21.8 [c.strings] Status: New Submitter: Jason Merrill Opened: 2013-01-29 Last modified: 2014-02-11

View other active issues in [c.strings].

View all other issues in [c.strings].

View all issues with New status.

Discussion:

Apparently C1X changes `__STDC_UTF_16__` and `__STDC_UTF_32__` from macros defined in `uchar.h` (and reflected in C++ by Table 79) to be predefined by the compiler. Do we want to do the same?

Proposed resolution:

### 2238. Problematic iterator-pair constructor of containers

Section: 21.8 [c.strings] Status: Open Submitter: Johannes Schaub Opened: 2013-02-02 Last modified: 2014-07-01

View other active issues in [c.strings].

View all other issues in [c.strings].

View all issues with Open status.

Discussion:

The non-explicit nature of the iterator-pair constructor of containers, such a

>     template <class InputIterator>
>     vector(InputIterator first, InputIterator last, const Allocator& = Allocator());

can be selected in unexpected situations, leading to a hard runtime error, as demonstrated by the following example:

>     #include <vector>

>     void f(std::vector<char> v){ /* ... */}

>     int main() {
>       f({"A", "B"});
>     }

The actually intended initializer-list constructor isn't feasible here, so the best match is the constructor template

>     template <class InputIterator>
>     vector(InputIterator first, InputIterator last, const Allocator& = Allocator());

This compiles, but will result in code running amok. The potential trap (that cannot be easily detected by the library implementation) could be reduced by making this constructor explicit. It would still have the effect to be selected here, but the code would be ill-formed, so the programmer gets a clear meassage here.

[2014-06 Rapperswil]

JW: can't fix this, don't want to touch this, Do The Right Thing clause has been a source of tricky issues. only really happens with string literals, that's the only way to create an array that isn't obviously an array

GR: want to see paper

AM: is it only string literals, or also UDLs?

STL: maybe, but we don't need to deal with that. This is only a problem in a very specific case

Leave as Open.

Proposed resolution:

### 2239. `min/max/minmax` requirements

Section: 25.4.7 [alg.min.max] Status: New Submitter: Juan Soulie Opened: 2013-01-26 Last modified: 2014-06-17

View other active issues in [alg.min.max].

View all other issues in [alg.min.max].

View all issues with New status.

Discussion:

25.4.7 [alg.min.max] requires type `T` in `min`, `max`, and `minmax` to be `LessThanComparable`, but I don't believe this should be required for the versions that take a `Compare` argument.

Paragraphs 1 to 4 of 25.4 [alg.sorting] should apply anyway, although I'm not sure about `Compare` being required to induce a strict weak ordering here.

Further, `min` and `max` also lack formal complexity guarantees.

[2014-06-07 Daniel comments and provides wording]

Certainly, the functions with `Compare` should not impose `LessThanComparable` requirements.

In regard to the question whether a strict weak ordering should be required as implied by the `Compare` requirements, I would like to point out that this is requirement is in fact needed, because the specification of the normative Remarks elements (e.g. "Returns the first argument when the arguments are equivalent.") do depend on the existence of a equivalence relation that can be relied on and this is also consistent with the same strict weak ordering requirement that is indirectly imposed by the `LessThanComparable` requirement set for functions referring to `operator<` (Let me note that the very same `StrictWeakOrder` language concept had intentionally been required for similar reasons during "concept-time" in N2914).

Proposed resolution:

This wording is relative to N3936.

1. Change 25.4.7 [alg.min.max] as indicated:

   >     template<class T> constexpr const T& min(const T& a, const T& b);
   >     template<class T, class Compare>
   >       constexpr const T& min(const T& a, const T& b, Compare comp);

   > > -1- Requires: For the first form, type `T` shall be Type `T` is `LessThanComparable` (Table 18).

   > > -2- Returns: The smaller value.

   > > -3- Remarks: Returns the first argument when the arguments are equivalent.

   > > -?- Complexity: Exactly one comparison.

   >     template<class T>
   >       constexpr T min(initializer_list<T> t);
   >     template<class T, class Compare>
   >       constexpr T min(initializer_list<T> t, Compare comp);

   > > -4- Requires: `T` is `LessThanComparable` and shall be `CopyConstructible` and `t.size() > 0`. For the first form, type `T` shall be `LessThanComparable`.

   > > -5- Returns: […]

   > > -6- Remarks: […]

   > > -?- Complexity: Exactly one comparison.

   >     template<class T> constexpr const T& max(const T& a, const T& b);
   >     template<class T, class Compare>
   >       constexpr const T& max(const T& a, const T& b, Compare comp);

   > > -7- Requires: For the first form, type `T` shall be Type `T` is `LessThanComparable` (Table 18).

   > > -8- Returns: […]

   > > -9- Remarks: […]

   > > -?- Complexity: Exactly one comparison.

   >     template<class T>
   >       constexpr T max(initializer_list<T> t);
   >     template<class T, class Compare>
   >       constexpr T max(initializer_list<T> t, Compare comp);

   > > -10- Requires: `T` is `LessThanComparable` and shall be `CopyConstructible` and `t.size() > 0`. For the first form, type `T` shall be `LessThanComparable`.

   > > -11- Returns: […]

   > > -12- Remarks: […]

   > > -?- Complexity: Exactly one comparison.

   >     template<class T> constexpr pair<const T&, const T&> minmax(const T& a, const T& b);
   >     template<class T, class Compare>
   >       constexpr pair<const T&, const T&> minmax(const T& a, const T& b, Compare comp);

   > > -13- Requires: For the first form, t Type `T` shall be `LessThanComparable` (Table 18).

   > > -14- Returns: […]

   > > -15- Remarks: […]

   > > -16- Complexity: Exactly one comparison.

   >     template<class T>
   >       constexpr pair<T, T> minmax(initializer_list<T> t);
   >     template<class T, class Compare>
   >       constexpr pair<T, T> minmax(initializer_list<T> t, Compare comp);

   > > -17- Requires: `T` is `LessThanComparable` and shall be `CopyConstructible` and `t.size() > 0`. For the first form, type `T` shall be `LessThanComparable`.

   > > -18- Returns: […]

   > > -19- Remarks: […]

   > > -20- Complexity: At most `(3/2) * t.size()` applications of the corresponding predicate.

### 2241. `<cstdalign>` and `#define` of `alignof`

Section: 18.10 [support.runtime] Status: Open Submitter: Richard Smith Opened: 2013-02-14 Last modified: 2014-03-03

View other active issues in [support.runtime].

View all other issues in [support.runtime].

View all issues with Open status.

Discussion:

According to 18.10 [support.runtime] p2:

> The contents of these headers are the same as the Standard C library headers [..], `<stdalign.h>`, [..]

Since our base C standard is C99, which doesn't have a `<stdalign.h>`, the reference to a non-existing C header is irritating (In this context `<stdalign.h>` doesn't refer to the deprecated C++ header `<stdalign.h>` described in D.5 [depr.c.headers]).

Furthermore, it would be also important that it doesn not define a macro named `alignof`, which C11 also defines in this header.

Currently we only have the following guarantee as part of 18.10 [support.runtime] p7:

> The header `<cstdalign>` and the header `<stdalign.h>` shall not define a macro named `alignas`.

It is unclear what the better strategy is: Striking the reference to `<stdalign.h>` in 18.10 [support.runtime] p2 or upgrading to C11 as new base C standard.

[2014-02-15 Issaquah]

STL: related to earlier issue on C4, 2201, and now we get a C11 header

JY: find _Alignof as keyword C11 FDIS has four defines in stdalign.h

AM: need paper for C11 as base library we should really do that

STL: really need vendor input

STL: don't think we need to do anything right now not P1

AM: any objections to downscale to P2 (no objections)

Proposed resolution:

### 2242. `[uninitialized_]copy_n()` defect

Section: 25.3.1 [alg.copy], 20.7.12.2 [uninitialized.copy] Status: New Submitter: Sean Parent Opened: 2013-02-14 Last modified: 2014-02-11

View all other issues in [alg.copy].

View all issues with New status.

Discussion:

`copy_n()` and `uninitialized_copy_n()` only return the output iterator, and not the input iterator. Likely the interface was simply copied from the original STL. Unfortunately the interface in the original STL contains a bug.

`copy_n()` and `uninitialized_copy_n()` must return the resulting input iterator as well as the output iterator (I would suggest returning a pair). Without this, there is no way to continue reading from an actual input iterator — and if it is really a forward iterator, it will cost `n` increments to get back to where you were.

Proposed resolution:

### 2243. `istream::putback` problem

Section: 27.7.2.3 [istream.unformatted] Status: New Submitter: Juan Soulie Opened: 2013-03-01 Last modified: 2014-02-11

View other active issues in [istream.unformatted].

View all other issues in [istream.unformatted].

View all issues with New status.

Discussion:

In 27.7.2.3 [istream.unformatted] / 34, when describing `putback`, it says that "`rdbuf->sputbackc()`" is called. The problem are not the obvious typos in the expression, but the fact that it may lead to different interpretations, since nowhere is specified what the required argument to `sputbackc` is.

It can be guessed to be "`rdbuf()->sputbackc(c)`", but "`rdbuf()->sputbackc(char_type())`" or just anything would be as conforming (or non-confoming) as the first guess.

Proposed resolution:

### 2244. Issue on `basic_istream::seekg`

Section: 27.7.2.3 [istream.unformatted] Status: New Submitter: Juan Soulie Opened: 2013-03-04 Last modified: 2014-02-11

View other active issues in [istream.unformatted].

View all other issues in [istream.unformatted].

View all issues with New status.

Discussion:

When issue 1445 was resolved by adopting N3168, it exposed the need to modify both overloads of `basic_istream::seekg` (by inserting "the function clears eofbit," after "except that"), but the fix applied to the text apparently forgets the second overload at 27.7.2.3 [istream.unformatted] p43.

[2013-10-17: Daniel provides concrete wording]

It seems that the tiny sentence "SIMILARLY for 27.7.1.3/43 (`seekg`)." had been overlooked. I agree that the wording needs to be applied here as well.

Proposed resolution:

This wording is relative to N3691.

1. Change 27.7.2.3 [istream.unformatted] p43 as indicated:

   >     basic_istream<charT,traits>& seekg(off_type off, ios_base::seekdir dir);

   > > -43- Effects: Behaves as an unformatted input function (as described in 27.7.2.3, paragraph 1), except that the function first clears `eofbit`, it does not count the number of characters extracted, and does not affect the value returned by subsequent calls to `gcount()`. […]

### 2245. `packaged_task::reset()` memory allocation

Section: 30.6.9.1 [futures.task.members] Status: New Submitter: Jonathan Wakely Opened: 2013-03-05 Last modified: 2014-02-11

View other active issues in [futures.task.members].

View all other issues in [futures.task.members].

View all issues with New status.

Discussion:

The effects of `packaged_task::reset()` result in memory allocation, but don't allow a user to provide an allocator.

`packaged_task::reset()` needs to be overloaded like so:

>     template<class Alloc>
>     void reset(const Alloc&);

Alternatively, the effects of `reset()` need to require the same allocator is used as at construction, which would require the constructor to store the allocator for later use.

I like to remark that GCC at the moment uses the second option, i.e. the allocator passed to the constructor (if any) is used to create the new shared state, because this didn't require any change to the interface.

Proposed resolution:

### 2248. `numeric_limits::is_iec559` misnamed

Section: 18.3.2 [limits] Status: New Submitter: Pete Becker Opened: 2013-03-08 Last modified: 2014-02-11

View all other issues in [limits].

View all issues with New status.

Discussion:

This member should probably be named "is_ieee754". Or at least the standard should explain that IEC-559 no longer exists, and that it's been superseded by IEEE-754.

Proposed resolution:

### 2250. Follow-up On Library Issue 2207

Section: 20.6.1 [bitset.cons], 20.6.2 [bitset.members], 21.4.2 [string.cons], 21.4.6 [string.modifiers], 21.4.7 [string.ops] Status: New Submitter: Frank Birbacher Opened: 2013-04-18 Last modified: 2014-05-23

View all other issues in [bitset.cons].

View all issues with New status.

Discussion:

Similar to LWG 2207 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. 20.6.1 [bitset.cons] p3+4

2. 20.6.2 [bitset.members] p13+14 (`set`)

3. 20.6.2 [bitset.members] p19+20 (`reset`)

4. 20.6.2 [bitset.members] p27+28 (`flip`)

5. 20.6.2 [bitset.members] p41+42 (`test`)

6. 21.4.2 [string.cons] p3+4

7. 21.4.6.2 [string::append] p3+4

8. 21.4.6.3 [string::assign] p4+5

9. 21.4.6.4 [string::insert] p1+2, p5+6, p9+10 (partially)

10. 21.4.6.5 [string::erase] p1+2

11. 21.4.6.6 [string::replace] p1+2, p5+6, p9+10 (partially)

12. 21.4.6.7 [string::copy] p1+2

13. 21.4.7.8 [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 30.3.1.5 [thread.thread.member]). The suggested wording applies a similar fix for these as well.

Proposed resolution:

This wording is relative to N3936.

1. Modify 20.6.1 [bitset.cons] as indicated: [Editorial comment: The wording form used to ammend the Throws element is borrowed from a similar style used in 21.4.6.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 position `pos` is other than `zero` or `one`. The function uses `traits::eq()` to compare the character values.

   > > […]

2. Modify 20.6.2 [bitset.members] as indicated:

   >     bitset<N>& 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<N>& 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<N>& 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 21.4.2 [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 21.4.4 [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 21.4.6.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 21.4.6.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 21.4.6.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 `length_error`, 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: Calls Equivalent 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 21.4.6.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 21.4.6.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 `length_error`, 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: Calls Equivalent 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 21.4.6.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 21.4.7.8 [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 30.3.1.5 [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.

### 2251. C++ library should define `ssize_t`

Section: 18.2 [support.types] Status: New Submitter: Matt Austern Opened: 2013-04-19 Last modified: 2014-02-11

View all other issues in [support.types].

View all issues with New status.

Discussion:

The C++ standard library defines `size_t`, a typedef for an implementation defined unsigned integer type that can represent the sizes of objects. The POSIX standard augments this with `ssize_t`, a typedef for a signed integer type that corresponds to `size_t`.

The `ssize_t` typedef is useful — useful enough that the C++ standard even refers to it. (In a non-normative footnote in 27.5.2 [stream.types].) Also, lots of OS vendors add it to their headers anyway, even though it isn't part of the C or C++ standards, because those vendors are trying to define headers that conform to multiple standards at once. We should make users' and implementers' lives easier by adding `ssize_t` to 18.2 [support.types].

[2013-09-29, Suggested wording from Jayson Oldfather]

I decided to use the phrase to describe `ssize_t` below because of the text describing it in the POSIX standard. In it, it describes `ssize_t` with the value range of `[-1,{SSIZE_MAX}]`. `SSIZE_MAX` is specified in the POSIX standard as a minimum value of `_POSIX_SSIZE_MAX`. This macro is referenced in the wording below.

Proposed resolution:

1. Ammend 18.2 [support.types], Table 30 as indicated:

   > Table 30 — Header `<cstddef>` synopsis
   > Type | Name(s)
   > --- | ---
   > Macros: | `NULL offset_t`
   > Types: | `ptrdiff_t ssize_t size_t max_align_t nullptr_t`

   Add the following paragraph to describe `ssize_t`

   > -?- The type `ssize_t` is an implementation-defined signed integer type that shall contain the minimum range `[-1, {SSIZE_MAX}]` where `SSIZE_MAX` is specified at a minimum of `_POSIX_SSIZE_MAX`.

   Ammend p7 as follows:

   > -7- [Note: It is recommended that implementations choose types for `ptrdiff_t, ssize_t,` and `size_t` whose integer conversion ranks …

### 2253. [arrays.ts] `dynarray` should state which container requirements aren't met

Section: X [dynarray.overview] Status: Ready Submitter: Jonathan Wakely Opened: 2013-04-23 Last modified: 2014-06-17

View all issues with Ready status.

Discussion:

Addresses: arrays.ts

X [dynarray.overview] p2 says:

> "Unless otherwise specified, all `dynarray` operations have the same requirements and semantics as specified in 23.2 [container.requirements]."

Some differences from 23.2 [container.requirements] are not explicitly specified, including at least the lack of a default constructor, copy assignment and `swap` member.

The wording could be similar to 23.3.2.1 [array.overview] which says "An array satisfies all of the requirements of a container and of a reversible container (23.2 [container.requirements]), except that a default constructed array object is not empty and that `swap` does not have constant complexity."

[2013-09 Chicago:]

Move to Deferred. This feature will ship after C++14 and should be revisited then.

[2014-06-06 pre-Rapperswil]

This issue has been reopened as arrays-ts.

[2014-06-16 Rapperswil]

Move to Ready

Proposed resolution:

1. Add to X [dynarray.overview] p2:

   -2- A `dynarray` satisfies all of the requirements of a container and of a reversible container (23.2 [container.requirements]), except for default construction, assignment and `swap`. Unless otherwise specified, all `dynarray` operations have the same requirements and semantics as specified in 23.2 [container.requirements].

### 2254. [arrays.ts] Is `dynarray` an allocator-aware container?

Section: 23.2.1 [container.requirements.general] Status: Open Submitter: Jonathan Wakely Opened: 2013-04-23 Last modified: 2014-06-17

View other active issues in [container.requirements.general].

View all other issues in [container.requirements.general].

View all issues with Open status.

Discussion:

Addresses: arrays.ts

23.2.1 [container.requirements.general] p3 says:

> "All of the containers defined in this Clause and in (21.4) except `array` meet the additional requirements of an allocator-aware container, as described in Table 99."

Is this true of `dynarray`? I believe the answer must be no because `dynarray` has no `allocator_type`, and morally should be no, so that operations are defined in terms of `std::allocator<T>`, which p13 says doesn't actually need to be used (which allows the elements to be default-initialized as is intended, rather than "default-inserted into the container" using an allocator.)

The requirement that "each element is constructed with uses-allocator construction" provides roughly equivalent behaviour to the "CopyInsertable into `X`" requirements for allocator-aware containers, allowing an allocator to control construction of the `dynarray` elements.

[2013-09 Chicago]

Move to Deferred. This feature will ship after C++14 and should be revisited then.

[2014-06-06 pre-Rapperswill]

This issue has been reopened as arrays-ts.

Proposed resolution:

1. Change to 23.2.1 [container.requirements.general] p13:

   -13- All of the containers defined in this Clause and in (21.4) except `array` and `dynarray` meet the additional requirements of an allocator-aware container, as described in Table 99.

### 2255. [arrays.ts] `dynarray` constructor ambiguity

Section: X [dynarray.cons] Status: Ready Submitter: Jonathan Wakely Opened: 2013-04-23 Last modified: 2014-06-17

View all issues with Ready status.

Discussion:

Addresses: arrays.ts

These constructors can interact badly::

>     template<class Alloc>
>       dynarray(size_type c, const Alloc& alloc);
>     dynarray(size_type c, const T& v);

Unless the second argument is a value of exactly the type `T` you will get the first constructor, i.e. all of these will fail to compile:

>     dynarray<long> dlong(1, 1);   // 1 is not long
>     dynarray<float> dflt(1, 1.0);  // 1.0 is not float
>     dynarray<int*> dptr(1, nullptr);  // nullptr is not int*
>     dynarray<void*> doh(1, 0);  // 0 is not void*

The `nullptr` case is particularly annoying, a user trying to do the right thing by saying `nullptr` instead of `NULL` still gets the wrong result.

The constructor taking an allocator requires that "`Alloc` shall meet the requirements for an Allocator" but doesn't actually say "shall not participate in overload resolution unless ..."

I believe we have no precedent for using SFINAE to check "the requirements for an Allocator" because it's a pretty complicated set of requirements. We could say it shall not participate in overload resolution if `Alloc` is implicitly convertible to `value_type`.

Alternatively, we could follow the same approach used by other types that can be constructed with an unconstrained allocator type and use `std::allocator_arg_t` as the first argument instead of adding an allocator after the other arguments.

[2013-09 Chicago:]

Move to Deferred. This feature will ship after C++14 and should be revisited then.

[2014-06-06 pre-Rapperswil]

This issue has been reopened as arrays-ts.

[2014-06-16 Rapperswil]

Move to Ready for alternative A

Previous resolution [SUPERSEDED]:

> 1. Either use the correct way to unambiguously call a constructor taking any type of allocator, i.e. change the constructors to take `dynarray(std::allocator_arg_t, const Alloc&, ...)` by modifying both the synopsis X [dynarray.overview] p2 and X [dynarray.cons] before p9 like so:

>    >     template <class Alloc>
>    >       dynarray(allocator_arg_t, const Alloc& a, size_type c, const Alloc& alloc);
>    >     template <class Alloc>
>    >       dynarray(allocator_arg_t, const Alloc& a, size_type c, const T& v, const Alloc& alloc);
>    >     template <class Alloc>
>    >       dynarray(allocator_arg_t, const Alloc& a, const dynarray& d, const Alloc& alloc);
>    >     template <class Alloc>
>    >       dynarray(allocator_arg_t, const Alloc& a, initializer_list<T>, const Alloc& alloc);

> 2. or constrain the problematic constructor by adding a new paragraph to X [dynarray.cons]:

>    >     template <class Alloc>
>    >       dynarray(size_type c, const Alloc& alloc);
>    >     template <class Alloc>
>    >       dynarray(size_type c, const T& v, const Alloc& alloc);
>    >     template <class Alloc>
>    >       dynarray(const dynarray& d, const Alloc& alloc);
>    >     template <class Alloc>
>    >       dynarray(initializer_list<T>, const Alloc& alloc);

>    > > -9- Requires: `Alloc` shall meet the requirements for an Allocator (17.6.3.5 [allocator.requirements]).

>    > > -10- Effects: Equivalent to the preceding constructors except that each element is constructed with uses-allocator construction (20.7.7.2 [allocator.uses.construction]).

>    > > -?- Remarks: The first constructor shall not participate in overload resolution unless `Alloc` is not implicitly convertible to `T`.

Proposed resolution:

1. Use the correct way to unambiguously call a constructor taking any type of allocator, i.e. change the constructors to take `dynarray(std::allocator_arg_t, const Alloc&, ...)` by modifying both the synopsis X [dynarray.overview] p2 and X [dynarray.cons] before p9 like so:

   >     template <class Alloc>
   >       dynarray(allocator_arg_t, const Alloc& a, size_type c, const Alloc& alloc);
   >     template <class Alloc>
   >       dynarray(allocator_arg_t, const Alloc& a, size_type c, const T& v, const Alloc& alloc);
   >     template <class Alloc>
   >       dynarray(allocator_arg_t, const Alloc& a, const dynarray& d, const Alloc& alloc);
   >     template <class Alloc>
   >       dynarray(allocator_arg_t, const Alloc& a, initializer_list<T>, const Alloc& alloc);

### 2256. On `vector` iterator invalidation

Section: 23.3.6.5 [vector.modifiers] Status: New Submitter: Howard Hinnant Opened: 2013-04-29 Last modified: 2014-02-11

View other active issues in [vector.modifiers].

View all other issues in [vector.modifiers].

View all issues with New status.

Discussion:

23.3.6.5 [vector.modifiers]/p3 says:

>     iterator erase(const_iterator position);
>     iterator erase(const_iterator first, const_iterator last);

> > Effects: Invalidates iterators and references at or after the point of the erase.

Consider this example:

>     #include <vector>
>     #include <cassert>

>     int main()
>     {
>       typedef std::vector<int> C;
>       C c = {1, 2, 3, 4};
>       C::iterator i = c.begin() + 1;
>       C::iterator j = c.end() - 1;
>       assert(*i == 2);
>       assert(*j == 4);
>       c.erase(c.begin());
>       assert(*i == 3); // Why is this not perfectly fine?!
>     }

Why has the iterator `i` been invalidated? It still refers to a perfectly reasonable, fully constructed object. If `vector::iterator` were to be implemented as a pointer (which is legal), it is not possible for that last line to do anything but run fine.

The iterator `j` on the other hand now points at end, and any iterators that may now point beyond `end()`, into uninitialized memory, are clearly invalid.

But why do we say that an iterator that must point to a valid object is invalid? This looks to me like we simply got sloppy in our specification.

Proposed resolution:

### 2259. Issues in 17.6.5.5 rules for member functions

Section: 17.6.5.5 [member.functions] Status: New Submitter: Richard Smith Opened: 2013-05-12 Last modified: 2014-02-11

View all other issues in [member.functions].

View all issues with New status.

Discussion:

17.6.5.5 [member.functions] p2 says:

> "An implementation may declare additional non-virtual member function signatures within a class:

> by adding arguments with default values to a member function signature; [Footnote: Hence, the address of a member function of a class in the C++ standard library has an unspecified type.] [Note: An implementation may not add arguments with default values to virtual, global, or non-member functions. — end note]

> by replacing a member function signature with default values by two or more member function signatures with equivalent behavior; and

> by adding a member function signature for a member function name."

1. This wording is not using the correct terminology. "by adding arguments with default values" presumably means "by adding parameters with default arguments", and likewise throughout.

2. This paragraph only allows an implementation to declare "additional" signatures, but the first bullet is talking about replacing a standard signature with one with additional parameters.

3. None of these bullets allows a member function with no ref-qualifier to be replaced by signatures with ref-qualifiers (a situation which was just discussed on std-proposals), and likewise for cv-qualifiers. Presumably that is not intentional, and such changes should be permissible.

I think the first two items are probably editorial, since the intent is clear.

[2013-12-11 Richard provides concrete wording]

Proposed resolution:

This wording is relative to N3797.

1. Merge 17.6.5.5 [member.functions]p2+3 as indicated:

   > -2- An implementation may declare additional non-virtual member function signatures within a class:

   > - by adding arguments with default values to a member function signature;188 [Note: An implementation may not add arguments with default values to virtual, global, or non-member functions. — end note]

   > - by replacing a member function signature with default values by two or more member function signatures with equivalent behavior; and

   > - by adding a member function signature for a member function name.

   > -3- A call to a member function signature described in the C++ standard library behaves as if the implementation declares no additional member function signatures.[Footnote: A valid C++ program always calls the expected library member function, or one with equivalent behavior. An implementation may also define additional member functions that would otherwise not be called by a valid C++ program.] For a non-virtual member function described in the C++ standard library, an implementation may declare a different set of member function signatures, provided that any call to the member function that would select an overload from the set of declarations described in this standard behaves as if that overload were selected. [Note: For instance, an implementation may add parameters with default values, or replace a member function with default arguments with two or more member functions with equivalent behavior, or add additional signatures for a member function name. — end note]

### 2260. Missing requirement for `Allocator::pointer`

Section: 17.6.3.5 [allocator.requirements] Status: Open Submitter: Jonathan Wakely Opened: 2013-05-14 Last modified: 2014-02-11

View other active issues in [allocator.requirements].

View all other issues in [allocator.requirements].

View all issues with Open status.

Discussion:

For an allocator `A<T>` which defines `A<T>::pointer` to a class type, i.e. not `T*`, I see no requirement that `A<T>::pointer` is convertible to `A<U>::pointer`, even if `T*` is convertible to `U*`. Such conversions are needed in containers to convert from e.g. `ListNodeBase*` to `ListNode<T>*`.

The obvious way to do such conversions appears to be `pointer_traits::pointer_to()`, but that's ill-formed if the static member function `A<T>::pointer::pointer_to()` doesn't exist and the allocator requirements don't mention that function, so you need to cast `A<T>::pointer` to `A<T>::void_pointer` then cast that to `A<U>::pointer`.

Is converting via `void_pointer` really intended, or are we missing a requirement that `pointer_traits<A<T>::pointer>::pointer_to()` be well-formed?

Proposed resolution:

Add to the Allocator requirements table the following requirement:

> The expression `pointer_traits<XX::pointer>::pointer_to(r)` is well-defined.

[2013-09 Chicago]

Pablo to come back with Proposed Wording

Proposed resolution:

1. Edit Table 28 as indicated:

   > Table 28 — Allocator requirements (continued)
   > Expression | Return type | Assertion/note pre-/post-condition | Default
   > --- | --- | --- | ---
   > `…`
   > `static_cast<X::const_pointer>(z)` | `X::const_pointer` | `static_cast<X::const_pointer>(z) == q` |
   > `pointer_traits<X::pointer>::pointer_to(r)` | `X::pointer` |  |
   > `…`

### 2261. Are containers required to use their '`pointer`' type internally?

Section: 23.2 [container.requirements] Status: New Submitter: Jonathan Wakely Opened: 2013-05-14 Last modified: 2014-06-17

View all other issues in [container.requirements].

View all issues with New status.

Discussion:

Is a container `C` only supposed to refer to allocated memory (blocks of contiguous storage, nodes, etc.) through objects of type `C::pointer` rather than `C::value_type*`?

I don't see anything explicitly requiring this, so a container could immediately convert the result of `get_allocator().allocate(1)` to a built-in pointer of type `value_type*` and only deal with the built-in pointer until it needs to deallocate it again, but that removes most of the benefit of allowing allocators to use custom pointer types.

[2014-06-12, Jonathan comments]

This issue is basically the same issue as LWG 1521, which agrees it's an issue, to be dealt with in the future, so I request that 2261 not be closed as a dup unless we reopen 1521.

Proposed resolution:

### 2262. Requirement for `unique_ptr<T>::get_deleter()(p)` to be able to destroy the `unique_ptr`

Section: 20.8.1.2 [unique.ptr.single] Status: New Submitter: Rob Desbois Opened: 2013-05-15 Last modified: 2014-02-11

View other active issues in [unique.ptr.single].

View all other issues in [unique.ptr.single].

View all issues with New status.

Discussion:

N3337 20.8.1.2.5 [unique.ptr.single.modifiers] contains 2 non-normative notes stating:

> [para 4]: "The order of these operations is significant because the call to `get_deleter()` may destroy `*this`."

> [para 5]: "The postcondition does not hold if the call to `get_deleter()` destroys `*this` since `this->get()` is no longer a valid expression."

It seems this wording was created to resolve 998 due to the possibility that a `unique_ptr` may be destroyed through deletion of its stored pointer where that directly or indirectly refers to the same `unique_ptr`. If `unique_ptr` is required to support circular references then it seems this must be normative text: an implementation is currently allowed to operate on `*this` after the assignment and deletion specified in para 4, since this is only 'disallowed' by the non-normative note.

I propose the following draft rewording:

[para 4]: Effects: assigns `p` to the stored pointer, and then if the old value of the stored pointer, `old_p`, was not equal to `nullptr`, calls `get_deleter()(old_p)`. No operation shall be performed after the call to `get_deleter()(old_p)` that requires `*this` to be valid, because the deletion may destroy `*this` if it is referred to directly or indirectly by the stored pointer. [Note: The order of these operations is significant because the call to `get_deleter()` may destroy `*this`. — end note]

[para 5]: Postconditions: If the call `get_deleter()(old_p)` destroyed `*this`, none. Otherwise, `get() == p`. [Note: The postcondition does not hold if the call to `get_deleter()` destroys `*this` since `this->get()` is no longer a valid expression. — end note]

I expect it will also be necessary to amend the requirements for a deleter, so in addition:

20.8.1.2 [unique.ptr.single] [para 1]: The default type for the template parameter `D` is `default_delete`. A client-supplied template argument `D` shall be a function object type (20.10), lvalue-reference to function, or lvalue-reference to function object type for which, given a value `d` of type `D` and a value `ptr` of type `unique_ptr<T, D>::pointer`, the expression `d(ptr)` is valid and has the effect of disposing of the pointer as appropriate for that deleter. Where `D` is not an lvalue reference type, `d(ptr)` shall be valid if `ptr` refers directly or indirectly to the invoking `unique_ptr` object.

[2013-10-05, Stephan T. Lavavej comments and provides alternative wording]

In Chicago, we determined that the original proposed change to 20.8.1.2 [unique.ptr.single]/1 was insufficient, because `d` might be a reference to a deleter functor that's destroyed during self-destruction.

We believed that 20.8.1.2.5 [unique.ptr.single.modifiers]/4 was already sufficiently clear. The Standard occasionally prevents implementations of `X` from doing various things, through the principle of "nothing allows `X` to fail in that situation". For example, `v.push_back(v[0])` is required to work for non-empty vectors because nothing allows that to fail. In this case, the intent to allow self-destruction is already clear.

Additionally, we did not believe that 20.8.1.2.5 [unique.ptr.single.modifiers]/5 had to be changed. The current note is slightly squirrely but it does not lead to confusion for implementers or users.

Previous resolution from Rob Desbois:

> 1. Edit 20.8.1.2 [unique.ptr.single] p1 as indicated:

>    > The default type for the template parameter `D` is `default_delete`. A client-supplied template argument `D` shall be a function object type (20.10), lvalue-reference to function, or lvalue-reference to function object type for which, given a value `d` of type `D` and a value `ptr` of type `unique_ptr<T, D>::pointer`, the expression `d(ptr)` is valid and has the effect of disposing of the pointer as appropriate for that deleter. Where `D` is not an lvalue reference type, `d(ptr)` shall be valid if `ptr` refers directly or indirectly to the invoking `unique_ptr` object.

> 2. Edit 20.8.1.2.5 [unique.ptr.single.modifiers] p4+5 as indicated:

>    >     void reset(pointer p = pointer()) noexcept;

>    > > -3- Requires: The expression `get_deleter()(get())` shall be well formed, shall have well-defined behavior, and shall not throw exceptions.

>    > > -4- Effects: assigns `p` to the stored pointer, and then if the old value of the stored pointer, `old_p`, was not equal to `nullptr`, calls `get_deleter()(old_p)`. No operation shall be performed after the call to `get_deleter()(old_p)` that requires `*this` to be valid, because the deletion may destroy `*this` if it is referred to directly or indirectly by the stored pointer. [Note: The order of these operations is significant because the call to `get_deleter()` may destroy `*this`. — end note]

>    > > -5- Postconditions: If the call `get_deleter()(old_p)` destroyed `*this`, none. Otherwise, `get() == p`. [Note: The postcondition does not hold if the call to `get_deleter()` destroys `*this` since `this->get()` is no longer a valid expression. — end note]

Proposed resolution:

This wording is relative to N3691.

1. Edit 20.8.1.2 [unique.ptr.single] p1 as indicated:

   > The default type for the template parameter `D` is `default_delete`. A client-supplied template argument `D` shall be a function object type (20.10), lvalue-reference to function, or lvalue-reference to function object type for which, given a value `d` of type `D` and a value `ptr` of type `unique_ptr<T, D>::pointer`, the expression `d(ptr)` is valid and has the effect of disposing of the pointer as appropriate for that deleter. `d(ptr)` shall be valid even if it triggers the destruction of `d` or (if `D` is an lvalue reference to function object type) the function object that `d` refers to.

### 2264. [arrays.ts] `std::dynarray` defines its initializer-list constructor in terms of a non-existent constructor

Section: X [dynarray], 23.2 [container.requirements] Status: Open Submitter: Povilas Kanapickas Opened: 2013-05-22 Last modified: 2014-06-17

View all issues with Open status.

Discussion:

Addresses: arrays.ts

`std::dynarray` member listing at X [dynarray.overview] includes this constructor:

>     dynarray(initializer_list<T>);

Also, X [dynarray.overview] p. 2 says:

> Unless otherwise specified, all `dynarray` operations have the same requirements and semantics as specified in 23.2.

The constructor in question isn't mentioned in X [dynarray.cons] or anywhere else. This means requirements from 23.2 [container.requirements] apply. However, Table 100 in 23.2.3 [sequence.reqmts] says:

> `X(il)` Equivalent to `X(il.begin(), il.end())`

`std::dynarray` does not provide this constructor.

The proposed resolution below adds the missing constructor and a complementary constructor with an allocator parameter. The new constructors, differently from the rest of containers, accept iterators that have forward iterator category. This is needed because the size requirements must be known in order to allocate appropriately-sized storage.

An alternative resolution could be to properly specify the initializer-list constructor.

[2013-09 Chicago:]

Move to Deferred. This feature will ship after C++14 and should be revisited then.

[2014-06-06 pre-Rapperswill]

This issue has been reopened as arrays-ts.

Proposed resolution:

1. Add the following to the `std::dynarray` synopsis at X [dynarray.overview]:

   >     namespace std {
   >       template <class T>
   >       class dynarray {
   >         […]
   >         // 23.3.4.2 construct/copy/destroy:
   >         […]
   >         template <class ForwardIterator>
   >         dynarray(ForwardIterator first, ForwardIterator last);
   >         template <class ForwardIterator, class Alloc>
   >         dynarray(ForwardIterator first, ForwardIterator last, const Alloc& alloc);
   >         […]
   >       };
   >     }

2. Add the following to X [dynarray.cons] after p. 8:

   >     template <class ForwardIterator>
   >     dynarray(ForwardIterator first, ForwardIterator last);

   > > -?- Requires: `T` shall meet the `CopyConstructible` requirements.

   > > -?- Effects: Allocates storage for `distance(first, last)` elements. The `distance(first, last)` elements of the dynarray are direct-initialized (8.5 [dcl.init]) with the corresponding elements from the range `[first,last)`. May or may not invoke the global `operator new`.

   > > -?- Complexity: `distance(first, last)`.

   > > -?- Throws: `std::bad_array_length` when the size requested is larger than implementable, `std::bad_alloc` when there is insufficient memory.

3. Add the following to the list of constructors at X [dynarray.cons] before p. 9:

>     template <class Alloc>
>     dynarray(size_type c, const Alloc& alloc);
>     template <class Alloc>
>     dynarray(size_type c, const T& v, const Alloc& alloc);
>     template <class Alloc>
>     dynarray(const dynarray& d, const Alloc& alloc);
>     template <class Alloc>
>     dynarray(initializer_list<T>, const Alloc& alloc);
>     template <class ForwardIterator, class Alloc>
>     dynarray(ForwardIterator first, ForwardIterator last, const Alloc& alloc);

### 2265. 29.3p9 appears to rule out some acceptable executions

Section: 29.3 [atomics.order] Status: New Submitter: Brian Demsky Opened: 2013-06-17 Last modified: 2013-10-15

View all other issues in [atomics.order].

View all issues with New status.

Discussion:

I believe that the following variation on IRIW should admit executions in which `c1 = d1 = 5` and `c2 = d2 = 0`. If this is allowed, then what is sequence of program evaluations for 29.3 [atomics.order] p9 that justifies the store to `z`? It seems that 29.3 [atomics.order] p9 should not allow this execution because one of the stores to `x` or `y` has to appear earlier in the sequence, each of the `fetch_adds` reads the previous load in the thread (and thus must appear later in the sequence), and 29.3 [atomics.order] p9 states that each load must read from the last prior assignment in the sequence.

>     atomic_int x;
>     atomic_int y;
>     atomic_int z;
>     int c1, c2, d1, d2;

>     static void a(void* obj)
>     {
>       atomic_store_explicit(&x, 5, memory_order_relaxed);
>     }

>     static void b(void* obj)
>     {
>       atomic_store_explicit(&y, 5, memory_order_relaxed);
>     }

>     static void c(void* obj)
>     {
>       c1 = atomic_load_explicit(&x, memory_order_relaxed);
>       // this could also be an atomic load if the address depends on c1:
>       c2 = atomic_fetch_add_explicit(&y, c1, memory_order_relaxed);
>     }

>     static void d(void* obj)
>     {
>       d1 = atomic_load_explicit(&y, memory_order_relaxed);
>       d2 = atomic_fetch_add_explicit(&x, d1, memory_order_relaxed);
>     }

>     int user_main(int argc, char** argv)
>     {
>       thrd_t t1, t2, t3, t4;

>       atomic_init(&x, 0);
>       atomic_init(&y, 0);

>       printf("Main thread: creating 4 threads\n");
>       thrd_create(&t1, (thrd_start_t)&a, NULL);
>       thrd_create(&t2, (thrd_start_t)&b, NULL);
>       thrd_create(&t3, (thrd_start_t)&c, NULL);
>       thrd_create(&t4, (thrd_start_t)&d, NULL);

>       thrd_join(t1);
>       thrd_join(t2);
>       thrd_join(t3);
>       thrd_join(t4);
>       printf("c1=%d c2=%d\n",c1,c2);
>       printf("d1=%d d2=%d\n",d1,d2);

>       // Can this store write 1000 (i.e., c1=d1=5, c2=d2=0)?
>       atomic_store(&z, (c1+d1)*100+c2+d2);

>       printf("Main thread is finished\n");

>       return 0;
>     }

It seems that the easiest fix is to allow a load in 29.3 [atomics.order] p9 to read from any prior store in the evaluation order.

That said, I would personally advocate the following: It seems to me that C/C++ atomics are in a bit of different situation than Java because:

1. People are expected to use relaxed C++ atomics in potentially racy situations, so it isn't clear that semantics as complicated as the JMM's causality would be sane.

2. People who use C/C++ atomics are likely to be experts and use them in a very controlled fashion. I would be really surprised if compilers would find any real wins by optimizing the use of atomics.

Why not do something like:

There is satisfaction DAG of all program evaluations. Each evaluation observes the values of variables as computed by some prior assignment in the DAG.

There is an edge `x->y` between two evaluations `x` and `y` if:

1. the evaluation `y` observes a value computed by the evaluation `x` or

2. the evaluation `y` is an atomic store, the evaluation `x` is an atomic load, and there is a condition branch c that may depend (intrathread dependence) on `x` and `x-sb->c` and `c-sb->y`.

This seems to allow reordering of relaxed atomics that processors do without extra fence instructions, allows most reorderings by the compiler, and gets rid of satisfaction cycles.

Proposed resolution:

### 2266. `vector` and `deque` have incorrect `insert` requirements

Section: 23.2.3 [sequence.reqmts] Status: Tentatively Ready Submitter: Ahmed Charles Opened: 2013-05-17 Last modified: 2014-05-23

View other active issues in [sequence.reqmts].

View all other issues in [sequence.reqmts].

View all issues with Tentatively Ready status.

Discussion:

According to Table 100 in n3485 23.2.3 [sequence.reqmts]/4 the notes for the expression `a.insert(p,i,j)` say:

> Requires: `T` shall be `EmplaceConstructible` into `X` from `*i`. For `vector`, if the iterator does not meet the forward iterator requirements (24.2.5), `T` shall also be `MoveInsertable` into `X` and `MoveAssignable`.

> Each iterator in the range `[i,j)` shall be dereferenced exactly once.

> pre: `i` and `j` are not iterators into `a`.

> Inserts copies of elements in `[i, j)` before `p`

There are two problems with that wording: First, the special constraints for `vector`, that are expressed to be valid for forward iterators only, are necessary for all iterator categories. Second, the same special constraints are needed for `deque`, too.

[2013-10-05, Stephan T. Lavavej comments and provides alternative wording]

In Chicago, we determined that the original proposed resolution was correct, except that it needed additional requirements. When `vector` `insert(p, i, j)` is called with input-only iterators, it can't know how many elements will be inserted, which is obviously problematic for insertion anywhere other than at the end. Therefore, implementations typically append elements (geometrically reallocating), followed by `rotate()`. Given forward+ iterators, some implementations append and `rotate()` when they determine that there is sufficient capacity. Additionally, `deque` `insert(p, i, j)` is typically implemented with prepending/appending, with a possible call to `reverse()`, followed by a call to `rotate()`. Note that `rotate()`'s requirements are strictly stronger than `reverse()`'s.

Therefore, when patching Table 100, we need to add `rotate()`'s requirements. Note that this does not physically affect code (implementations were already calling `rotate()` here), and even in Standardese terms it is barely noticeable — if an element is `MoveInsertable` and `MoveAssignable` then it is almost certainly `MoveConstructible` and swappable. However, this patch is necessary to be strictly correct.

Previous resolution from Ahmed Charles:

> 1. Change Table 100 as indicated:

>    > Table 100 — Sequence container requirements (in addition to container) (continued)
>    > Expression | Return type | Assertion/note pre-/post-condition
>    > --- | --- | ---
>    > `…`
>    > `a.insert(p,i,j)` | `iterator` | Requires: `T` shall be `EmplaceConstructible` into `X` from `*i`. For `vector` and `deque`, if the iterator does not meet the forward iterator requirements (24.2.5), `T` shall also be `MoveInsertable` into `X` and `MoveAssignable`. Each iterator in the range `[i,j)` shall be dereferenced exactly once. pre: `i` and `j` are not iterators into `a`. Inserts copies of elements in `[i, j)` before `p`
>    > `…`

[2014-02-15 post-Issaquah session : move to Tentatively Ready]

Pablo: We might have gone too far with the fine-grained requirements. Typically these things come in groups.

Alisdair: I think the concepts folks assumed we would take their guidance.

Move to Tentatively Ready.

Proposed resolution:

1. Change Table 100 as indicated:

   > Table 100 — Sequence container requirements (in addition to container) (continued)
   > Expression | Return type | Assertion/note pre-/post-condition
   > --- | --- | ---
   > `…`
   > `a.insert(p,i,j)` | `iterator` | Requires: `T` shall be `EmplaceConstructible` into `X` from `*i`. For `vector` and `deque`, if the iterator does not meet the forward iterator requirements (24.2.5), `T` shall also be `MoveInsertable` into `X`, `MoveConstructible`, and `MoveAssignable`, and swappable (17.6.3.2 [swappable.requirements]). Each iterator in the range `[i,j)` shall be dereferenced exactly once. pre: `i` and `j` are not iterators into `a`. Inserts copies of elements in `[i, j)` before `p`
   > `…`

### 2267. `partial_sort_copy` underspecified for ranges of two different types

Section: 25.4.1.4 [partial.sort.copy] Status: New Submitter: Matt Austern Opened: 2013-06-26 Last modified: 2014-02-11

View all issues with New status.

Discussion:

The signature of this function is:

>     template<class InputIterator, class RandomAccessIterator>
>     RandomAccessIterator
>     partial_sort_copy(InputIterator first, InputIterator last,
>                       RandomAccessIterator result_first,
>                       RandomAccessIterator result_last);

(and the usual overload for an explicitly provided comparison function). The standard says nothing about requirements in the case where the input type (`iterator_traits<InputIterator>::value_type`) and the output type (`iterator_traits<RandomAccessIterator>::value_type`) are different.

Presumably the input type must be convertible to the output type. What's less clear is what the requirements are on the comparison operator. Does the algorithm only perform comparisons on two values of the output type, or does it also perform comparisons on values of the input type, or might it even perform heterogeneous comparisons?

Proposed resolution:

### 2269. Container iterators and argument-dependent lookup

Section: 23.2.1 [container.requirements.general] Status: New Submitter: Matt Austern Opened: 2013-06-26 Last modified: 2014-02-11

View other active issues in [container.requirements.general].

View all other issues in [container.requirements.general].

View all issues with New status.

Discussion:

Consider the following code snippet:

>     #include <vector>
>     #include <algorithm>

>     int main() {
>       std::vector<int> v1(100, 3);
>       std::vector<int> v2(100);
>       copy(v1.begin(), v1.end(), v2.begin());
>     }

It compiles without error on my desktop. Is it required to? I can't find evidence from the standard that it is. In my test `std::copy` was found by argument-dependent lookup because the implementation I used made `std::vector<int>::iterator` a user-defined type defined in namespace `std`. But the standard only requires `std::vector<int>::iterator` to be an implementation specified random access iterator type. I can't find anything requiring it to be a user-defined type at all (and in fact there are reasonable implementation where it isn't), let alone a user defined type defined in a specific namespace.

Since the defining namespace of container iterators is visible to users, should the standard say anything about what that namespace is?

Proposed resolution:

### 2273. `regex_match` ambiguity

Section: 28.11.2 [re.alg.match] Status: Open Submitter: Howard Hinnant Opened: 2013-07-14 Last modified: 2014-07-01

View all other issues in [re.alg.match].

View all issues with Open status.

Discussion:

28.11.2 [re.alg.match] p2 in describing regex_match says:

> -2- Effects: Determines whether there is a match between the regular expression `e`, and all of the character sequence `[first,last)`. The parameter `flags` is used to control how the expression is matched against the character sequence. Returns true if such a match exists, false otherwise.

It has come to my attention that different people are interpreting the first sentence of p2 in different ways:

1. If a search of the input string using the regular expression `e` matches the entire input string, `regex_match` should return true.

2. Search the input string using the regular expression `e`. Reject all matches that do not match the entire input string. If a such a match is found, return true.

The difference between these two subtly different interpretations is found using the following ECMAScript example:

>     std::regex re("Get|GetValue");

Using `regex_search`, this `re` can never match the input string `"GetValue"`, because ECMA specifies that alternations are ordered, not greedy. As soon as `"Get"` is matched in the left alternation, the matching algorithm stops.

Using definition 1, `regex_match` would return false for an input string of `"GetValue"`.

However definition 2 alters the grammar and appears equivalent to augmenting the regex with a trailing `'$'`, which is an anchor that specifies, reject any matches which do not come at the end of the input sequence. So, using definition 2, `regex_match` would return true for an input string of `"GetValue"`.

My opinion is that it would be strange to have `regex_match` return true for a `string/regex` pair that `regex_search` could never find. I.e. I favor definition 1.

John Maddock writes:

The intention was always that `regex_match` would reject any match candidate which didn't match the entire input string. So it would find `GetValue` in this case because the `"Get"` alternative had already been rejected as not matching. Note that the comparison with ECMA script is somewhat moot, as ECMAScript defines the regex grammar (the bit we've imported), it does not define anything like `regex_match`, nor do we import from ECMAScript the behaviour of that function. So IMO the function should behave consistently regardless of the regex dialect chosen. Saying "use awk regexes" doesn't cut it, because that changes the grammar in other ways.

(John favors definition 2).

We need to clarify 28.11.2 [re.alg.match]/p2 in one of these two directions.

[2014-06-21, Rapperswil]

AM: I think there's a clear direction and consensus we agree with John Maddock's position, and if noone else thinks we need the other function I won't ask for it.

Marshall Clow and STL to draft.

Proposed resolution:

### 2274. Does `map::operator[]` value-initialize or default-insert a missing element?

Section: 23.4.4.3 [map.access], 23.5.4.3 [unord.map.elem] Status: Open Submitter: Andrzej Krzemieński Opened: 2013-07-16 Last modified: 2014-02-11

View all other issues in [map.access].

View all issues with Open status.

Discussion:

Suppose that I provide a custom allocator for type `int`, that renders value 1 rather than 0 in default-insertion:

>     struct Allocator1 : std::allocator<int>
>     {
>       using super = std::allocator<int>;

>       template<typename Up, typename... Args>
>       void construct(Up* p, Args&&... args)
>       { super::construct(p, std::forward<Args>(args)...); }

>       template<typename Up>
>       void construct(Up* p)
>       { ::new((void*)p) Up(1); }
>     };

Now, if I use this allocator with `std::map`, and I use `operator[]` to access a not-yet-existent value, what value of the `mapped_type` should be created? 0 (value-initialization) or 1 (default-insertion):

>     map<string, int, less<string>, Allocator1> map;
>     cout << map["cat"];

N3960 is not very clear. 23.4.4.3 [map.access] in para 1 says:

> "If there is no key equivalent to `x` in the map, inserts `value_type(x, T())` into the map."

So, it requires value-initialization.

But para 2 says:

> "`mapped_type` shall be `DefaultInsertable` into `*this`."

This implies default-insertion, because if not, why the requirement. Also similar functions like `vector::resize` already require default-insertion wherever they put `DefaultInsertable` requirements.

Not to mention that default-insertion is more useful, because it allows custom allocators to "override" the default value of `mapped_type`.

[2013-09 Chicago]

Alisdair: Matters only for POD or trivial types

Marshall: issue might show up elsewhere other than `map<>`

Alisdair: initialize elements in any containers — by calling construct on allocator traits

Marshall: existing wording is clear

Alisdair: main concern is difference in wording, discusses default initialization

Nico: different requirement needed

Alisdair: gut is issue is NAD, brings up `DefaultInsertable` definition — discusses definition

Nico: why do we have the requirement?

Alisdair: other containers have this requirement

Marshall: this applies to many other containers

Nico: `deque<>` in particular

Alisdair: discusses allocator construct

Alisdair: wording raises concerns that aren't said in existing standard

Nico: sees no benefit to change

Marshall: leery of change

Alisdair: can be made clearer; might need to add note to `DefaultInsertable`; borderline editorial, comfortable without note, willing to wait until other issues arise. close issue as NAD

Proposed resolution:

This wording is relative to N3691.

1. Change 23.4.4.3 [map.access] p1+p5 as indicated:

   >     T& operator[](const key_type& x);

   > > -1- Effects: If there is no key equivalent to `x` in the map, inserts `value_type(x, T())` into the map into the map a value with `key_type` initialized using expression `x` and `mapped_type` initialized by default-insertion.

   > > -2- Requires: `key_type` shall be `CopyInsertable` and `mapped_type` shall be `DefaultInsertable` into `*this`.

   > > […]

   >     T& operator[](key_type&& x);

   > > -5- Effects: If there is no key equivalent to `x` in the map, inserts `value_type(std::move(x), T())` into the map into the map a value with `key_type` initialized using expression `std::move(x)` and `mapped_type` initialized by default-insertion.

   > > -6- Requires: `mapped_type` shall be `DefaultInsertable` into `*this`.

2. Change 23.5.4.3 [unord.map.elem] p2 as indicated:

   >     mapped_type& operator[](const key_type& k);
   >     mapped_type& operator[](key_type&& k);

   > > -1- Requires: `mapped_type` shall be `DefaultInsertable` into `*this`. For the first operator, `key_type` shall be `CopyInsertable` into `*this`. For the second operator, `key_type` shall be `MoveConstructible`.

   > > -2- Effects: If the `unordered_map` does not already contain an element whose key is equivalent to `k`, the first operator inserts the value `value_type(k, mapped_type())`a value with `key_type` initialized using expression `x` and `mapped_type` initialized by default-insertion and the second operator inserts the value `value_type(std::move(k), mapped_type())`a value with `key_type` initialized using expression `std::move(x)` and `mapped_type` initialized by default-insertion.

### 2276. Missing requirement on `std::promise::set_exception`

Section: 30.6 [futures] Status: New Submitter: Jonathan Wakely Opened: 2013-07-30 Last modified: 2013-10-15

View all other issues in [futures].

View all issues with New status.

Discussion:

The standard does not specify the behaviour of this program:

>     #include <future>
>     #include <cassert>

>     struct NonTrivial
>     {
>       NonTrivial() : init(true) { }
>       ~NonTrivial() { assert(init); }
>       bool init;
>     };

>     int main()
>     {
>       std::promise<NonTrivial> p;
>       auto f = p.get_future();
>       p.set_exception(std::exception_ptr());
>       f.get();
>     }

The standard doesn't forbid making the state ready with a null `exception_ptr`, so what should `get()` return? There's no stored exception to throw, but it can't return a value because none was initialized.

A careful reading of the standard shows 30.6.4 [futures.state] p8 says "A shared state is ready only if it holds a value or an exception ready for retrieval." One can infer from the fact that `set_exception()` makes the state ready that it must store a value or exception, so cannot store "nothing", but that isn't explicit.

The `promise::set_exception()` and `promise::set_exception_at_thread_exit()` members should require `p != nullptr` or should state the type of exception thrown if `p` is null.

Proposed resolution:

### 2277. [arrays.ts] `<dynarray>` is missing in 24.7/1

Section: 24.7 [iterator.range] Status: Open Submitter: Cassio Neri Opened: 2013-07-31 Last modified: 2014-06-17

View all other issues in [iterator.range].

View all issues with Open status.

Discussion:

Addresses: arrays.ts

Section 24.7 [iterator.range] p1 specifies header files that, in addition to `<iterator>`, make available the function templates in 24.7 (`begin`, `end`, etc.) but it fails to mention `<dynarray>`. This seems to be just an oversight.

[2013-09 Chicago:]

Move to Deferred. This feature will ship after C++14 and should be revisited then.

[2014-06-06 pre-Rapperswill]

This issue has been reopened as arrays-ts.

Proposed resolution:

This wording is relative to N3691.

1. Modify 24.7 [iterator.range] p1 as indicated:

   > -1- In addition to being available via inclusion of the `<iterator>` header, the function templates in 24.7 are available when any of the following headers are included: `<array>`, `<deque>`, `<dynarray>`, `<forward_list>`, `<list>`, `<map>`, `<regex>`, `<set>`, `<string>`, `<unordered_map>`, `<unordered_set>`, and `<vector>`.

### 2286. `stringbuf::underflow()` underspecified

Section: 27.8.2.4 [stringbuf.virtuals] Status: New Submitter: Sergey Zubkov Opened: 2013-08-29 Last modified: 2014-02-11

View all other issues in [stringbuf.virtuals].

View all issues with New status.

Discussion:

In 27.8.2.4 [stringbuf.virtuals]/1, `basic_stringbuf::underflow()` is specified to unconditionally return `traits::eof()` when a read position is not available.

The semantics of `basic_stringbuf` require, and existing libraries implement it so that this function makes a read position available if possible to do so, e.g. if some characters were inserted into the stream since the last call to `overflow()`, resulting in `pptr() > egptr()`. Compare to the conceptually similar D.7.1.3 [depr.strstreambuf.virtuals]/15.

Proposed resolution:

This wording is relative to N3691.

1. Change 27.8.2.4 [stringbuf.virtuals] as indicated:

   >     int_type underflow();

   > > -1- Returns: If the input sequence has a read position available or the function makes a read position available (as described below), returns `traits::to_int_type(*gptr())`. Otherwise, returns `traits::eof()`. Any character in the underlying buffer which has been initialized is considered to be part of the input sequence.

   > > -?- The function can make a read position available only if `(mode & ios_base::in) != 0` and if the write next pointer `pptr()` is not null and is greater than the current read end pointer `egptr()`. To make a read position available, the function alters the read end pointer `egptr()` to equal `pptr()`.

### 2289. `constexpr` guarantees of defaulted functions still insufficient

Section: 20.3.2 [pairs.pair], 20.4.2.1 [tuple.cnstr], 20.12.5 [time.duration] Status: New Submitter: Daniel Krügler Opened: 2013-09-09 Last modified: 2014-02-11

View all other issues in [pairs.pair].

View all issues with New status.

Discussion:

During the acceptance of N3471 and some similar `constexpr` papers, specific wording was added to `pair`, `tuple`, and other templates that were intended to impose implementation constraints that ensure that the observable `constexpr` "character" of a defaulted function template is solely determined by the required expressions of the user-provided types when instantiated, for example:

> The defaulted move and copy constructor, respectively, of pair shall be a `constexpr` function if and only if all required element-wise initializations for copy and move, respectively, would satisfy the requirements for a `constexpr` function.

This wording doesn't require enough, especially since the core language via CWG 1358 does now support `constexpr` function template instantiations, even if such function cannot appear in a constant expression (as specified in 5.19 [expr.const]) or as a constant initializer of that object (as specified in 3.6.2 [basic.start.init]). The wording should be improved and should require valid uses in constant expressions and as constant initializers instead.

Proposed resolution:

This wording is relative to N3691.

1. Change 20.3.2 [pairs.pair] p2 as indicated:

   > -2- The defaulted move and copy constructor, respectively, of pair shall be a `constexpr` function if and only if all required element-wise initializations for copy and move, respectively, would satisfy the requirements for a `constexpr` function An invocation of the move or copy constructor of `pair` shall be a constant expression (5.19 [expr.const]) if all required element-wise initializations would be constant expressions. An invocation of the move or copy constructor of `pair` shall be a constant initializer for that `pair` object (3.6.2 [basic.start.init]) if all required element-wise initializations would be constant initializers for the respective subobjects.

2. Change 20.4.2.1 [tuple.cnstr] p2 as indicated:

   > -2- The defaulted move and copy constructor, respectively, of `tuple` shall be a `constexpr` function if and only if all required element-wise initializations for copy and move, respectively, would satisfy the requirements for a `constexpr` function. The defaulted move and copy constructor of `tuple<>` shall be `constexpr` functions An invocation of the move or copy constructor of `tuple` shall be a constant expression (5.19 [expr.const]) if all required element-wise initializations would be constant expressions. An invocation of the move or copy constructor of `tuple` shall be a constant initializer for that `tuple` object (3.6.2 [basic.start.init]) if all required element-wise initializations would be constant initializers for the respective subobjects. An invocation of the move or copy constructor of `tuple<>` shall be a constant expression, or a constant initializer for that `tuple<>` object, respectively, if the function argument would be constant expression.

3. Change 20.12.5 [time.duration] p7 as indicated:

   > -7- Remarks: The defaulted copy constructor of duration shall be a `constexpr` function if and only if the required initialization of the member `rep_` for copy and move, respectively, would satisfy the requirements for a `constexpr` function.An invocation of the copy constructor of `duration` shall be a constant expression (5.19 [expr.const]) if the required initialization of the member `rep_` would be a constant expression. An invocation of the copy constructor of `duration` shall be a constant initializer for that `duration` object (3.6.2 [basic.start.init]) if the required initialization of the member `rep_` would be constant initializers for this subobject.

### 2290. Top-level "SFINAE"-based constraints should get a separate definition in Clause 17

Section: 20.10 [meta] Status: New Submitter: Daniel Krügler Opened: 2013-09-02 Last modified: 2014-06-17

View all other issues in [meta].

View all issues with New status.

Discussion:

The current library specification uses at several places wording that is intended to refer to core language template deduction failure at the top-level of expressions (aka "SFINAE"), for example:

> The expression `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated operand (Clause 5). Access checking is performed as if in a context unrelated to `T` and `U`. Only the validity of the immediate context of the assignment expression is considered. [Note: The compilation of the expression can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. — end note]

Similar wording can be found in the specification of `result_of`, `is_constructible`, and `is_convertible`, being added to resolve an NB comment by LWG 1390 and 1391 through N3142.

This wording is necessary to limit speculative compilations needed to implement these traits, but it is also lengthy and repetitive.

[2014-05-19, Daniel suggests a descriptive term]

constrictedly well-formed expression:

An expression e depending on a set of types `A1`, ..., `An` which is well-formed when treated as an unevaluated operand (Clause 5). Access checking is performed as if in a context unrelated to `A1`, ..., `An`. Only the validity of the immediate context of e is considered. [Note: The compilation of the expression can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. — end note]

[2014-05-20, Richard and Jonathan suggest better terms]

Richard suggested "locally well-formed"

Jonathan suggested "contextually well-formed" and then "The expression ... is valid in a contrived argument deduction context"

[2014-06-07, Daniel comments and improves wording]

The 2014-05-19 suggestion did only apply to expressions, but there are two important examples that are not expressions, but instead are involving an object definition (`std::is_constructible`) and a function definition (`std::is_convertible`), respectively, instead. Therefore I suggest to rephrase the usage of "expression" into "program construct" in the definition of Jonathan's suggestion of "valid in a contrived argument deduction context".

I would like to point out that given the new definition of "valid in a contrived argument deduction context", there are several other places of the Library specification that could take advantage of this wording to improve the existing specification, such as 20.9.11.2 [func.wrap.func] p2, most functions in 20.7.8.2 [allocator.traits.members], and the `**Insertable`, `EmplaceConstructible`, and `Erasable` definitions in 23.2.1 [container.requirements.general], but given that these are not fully described in terms of the aforementioned wording yet, I would recommend to fix them by a separate issue once the committee has agreed on following the suggestion presented by this issue.

Proposed resolution:

This wording is relative to N3936.

1. Add the following new definition to 17.3 [definitions] as indicated:

   valid in a contrived argument deduction context [defns.valid.contr.context]

   A program construct c depending on a set of types `A1`, ..., `An`, and treated as an unevaluated operand (Clause 5) when c is an expression, which is well-formed. Access checking is performed as if in a context unrelated to `A1`, ..., `An`. Only the validity of the immediate context (14.8.2 [temp.deduct]) of c is considered. [Note: The compilation of c can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. — end note].

2. Change Table 49 ("Type property predicates") as indicated:

   > Table 49 — Type property predicates
   > Template | Condition | Preconditions
   > --- | --- | ---
   > `…`
   > `template <class T, class U> struct is_assignable;` | The expression `declval<T>() = declval<U>()` is valid in a contrived argument deduction context ([defns.valid.contr.context]) for types `T` and `U`. well-formed when treated as an unevaluated operand (Clause 5). Access checking is performed as if in a context unrelated to `T` and `U`. Only the validity of the immediate context of the assignment expression is considered. [Note: The compilation of the expression can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. — end note] | […]
   > `…`

3. Change 20.10.4.3 [meta.unary.prop] p7 as indicated:

   > -7- Given the following function prototype:

   > >     template <class T>
   > >       add_rvalue_reference_t<T> create() noexcept;

   > the predicate condition for a template specialization `is_constructible<T, Args...>` shall be satisfied if and only if the following variable definition would be well-formed for some invented variable `t` would be valid in a contrived argument deduction context ([defns.valid.contr.context]) for types `T` and `Args...`:

   > >     T t(create<Args>()...);

   > [Note: These tokens are never interpreted as a function declaration. — end note] Access checking is performed as if in a context unrelated to `T` and any of the `Args`. Only the validity of the immediate context of the variable initialization is considered. [Note: The evaluation of the initialization can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. — end note]

4. Change Table 57 ("Other transformations") as indicated:

   > Table 57 — Other transformations
   > Template | Condition | Comments
   > --- | --- | ---
   > `…`
   > `template <class Fn, class... ArgTypes> struct result_of<Fn(ArgTypes...)>;` | […] | If the expression `INVOKE(declval<Fn>(), declval<ArgTypes>()...)` is valid in a contrived argument deduction context ([defns.valid.contr.context]) for types `Fn` and `ArgTypes...` well formed when treated as an unevaluated operand (Clause 5), the member typedef type shall name the type `decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...))`; otherwise, there shall be no member type. Access checking is performed as if in a context unrelated to `Fn` and `ArgTypes`. Only the validity of the immediate context of the expression is considered. [Note: The compilation of the expression can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. — end note]
   > `…`

5. Change 20.10.6 [meta.rel] p4 as indicated:

   > -4- Given the following function prototype:

   > >     template <class T>
   > >       add_rvalue_reference_t<T> create() noexcept;

   > the predicate condition for a template specialization `is_convertible<From, To>` shall be satisfied if and only if the return expression in the following code would be well-formed valid in a contrived argument deduction context ([defns.valid.contr.context]) for types `To` and `From`, including any implicit conversions to the return type of the function:

   > >     To test() {
   > >       return create<From>();
   > >     }

   > [Note: This requirement gives well defined results for reference types, `void` types, array types, and function types. — end note] Access checking is performed as if in a context unrelated to `To` and `From`. Only the validity of the immediate context of the expression of the return-statement (including conversions to the return type) is considered. [Note: The evaluation of the conversion can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. — end note]

### 2292. Find a better phrasing for "shall not participate in overload resolution"

Section: 17.5.1.4 [structure.specifications] Status: New Submitter: Jeffrey Yasskin Opened: 2013-09-03 Last modified: 2014-02-10

View all other issues in [structure.specifications].

View all issues with New status.

Discussion:

The C++14 CD has 25 sections including the phrase "X shall not participate in overload resolution ...". Most of these uses are double negatives, which are hard to interpret. "shall not ... unless" tends to be the easiest to read, since the condition is true when the function is available, but we also have a lot of "if X is not Y, then Z shall not participate", which actually means "You can call Z if X is Y." The current wording is also clumsy and long-winded. We should find a better and more concise phrasing.

As an initial proposal, I'd suggest using "X is enabled if and only if Y" in prose and adding an "Enabled If: ..." element to 17.5.1.4 [structure.specifications].

Daniel:

I suggest to name this new specification element for 17.5.1.4 [structure.specifications] as "Template Constraints:" instead, because the mentioned wording form was intentionally provided starting with LWG 1237 to give implementations more freedom to realize the concrete constraints. Instead of the original `std::enable_if`-based specifications we can use better forms of "SFINAE" constraints today and it eases the path to possible language-based constraints in the future.

Proposed resolution:

### 2294. `<cstdlib>` should declare `abs(double)`

Section: 26.8 [c.math] Status: Open Submitter: Pete Becker Opened: 2013-09-04 Last modified: 2014-02-13

View other active issues in [c.math].

View all other issues in [c.math].

View all issues with Open status.

Discussion:

… and `abs(float)` and `abs(long double)`. And `<cmath>` should declare `abs(int)`, `abs(long)`, and `abs(long long)`.

As things currently stand, this program is illegal:

>     #include <cstdlib>

>     int main() {
>       double d = -1.23;
>       double dd = std::abs(d);
>       return 0;
>     }

The call is ambiguous because of the various integer overloads, that's because `<cstdlib>` provides `abs(int)` but not `abs(double)`.

This lead one commenter on Stackoverflow to state that `abs` is dangerous, and to recommend using `fabs` instead.

In general, it makes sense to declare overloaded functions that take user-defined types in the same header as the definition of the user-defined types; it isn't necessary to declare all of the overloads in the same place. But here we're not dealing with any user-defined types; we're dealing with builtin types, which are always defined; all of the overloads should be defined in the same place, to avoid mysterious problems like the one in the code above.

The standard library has six overloads for `abs`:

>     int abs(int);  // <cstdlib>
>     long abs(long); // <cstdlib>
>     long long abs(long long); // <cstdlib>

>     float abs(float); // <cmath>
>     double abs(double); // <cmath>
>     long double abs(long double); // <cmath>

These should all be declared in both headers.

I have no opinion on `<stdlib.h>` and `<math.h>`.

[2013-09 Chicago]

This issue is related to LWG 2192

Move to open

[2014-02-13 Issaquah — Nicolai Josuttis suggest wording]

Proposed resolution:

1. Edit 26.8 [c.math] after p7 as indicated:

   > -6- In addition to the `int` versions of certain math functions in `<cstdlib>`, C++ adds `long` and `long long` overloaded versions of these functions, with the same semantics.

   > -7- The added signatures are:

   > >     long abs(long);                    // labs()
   > >     long long abs(long long);          // llabs()
   > >     ldiv_t div(long, long);            // ldiv()
   > >     lldiv_t div(long long, long long); // lldiv()

   > -?- To avoid ambiguities, C++ also adds the following overloads of `abs()` to `<cstdlib>`, with the semantics defined in `<cmath>`:

   > >     float abs(float);
   > >     double abs(double);
   > >     long double abs(long double);

   > -?- To avoid ambiguities, C++ also adds the following overloads of `abs()` to `<cmath>`, with the semantics defined in `<cstdlib>`:

   > >     int abs(int);
   > >     long abs(long);
   > >     long long abs(long long);

### 2295. Locale name when the provided `Facet` is a `nullptr`

Section: 22.3.1.2 [locale.cons] Status: New Submitter: Juan Soulie Opened: 2013-09-04 Last modified: 2014-02-11

View all issues with New status.

Discussion:

22.3.1.2 [locale.cons] p14 ends with:

> "[…] If `f` is null, the resulting object is a copy of `other`."

but the next line p15 says:

> "Remarks: The resulting locale has no name."

But both can't be true when `other` has a name and `f` is null.

I've tried it on two implementations (MSVC,GCC) and they are inconsistent with each other on this.

Daniel Krügler:

As currently written, the Remarks element applies unconditionally for all cases and thus should "win". The question arises whether the introduction of this element by LWG 424 had actually intended to change the previous Note to a Remarks element. In either case the wording should be improved to clarify this special case.

Proposed resolution:

### 2296. `std::addressof` should be `constexpr`

Section: 20.7.12.1 [specialized.addressof] Status: New Submitter: Daryle Walker Opened: 2013-09-08 Last modified: 2014-06-17

View all other issues in [specialized.addressof].

View all issues with New status.

Discussion:

I'm writing a function that needs to be `constexpr` and I wanted to take the address of its input. I was thinking of using `std::addressof` to be safe, but it isn't currently `constexpr`. A sample implementation couldn't be `constexpr` under the C++11 rules, though.

Daniel Krügler:

Indeed the core language clarified by CWG 1312 and by CWG 1384, that such emulations of `std::addressof` implementations are not valid in constant expressions, therefore it seems more like a defect than a feature request to ask for the guarantee that `std::addressof` is a `constexpr` function. It should be added that a similar requirement already exists for `offsetof` indirectly via the C99 standard as of 7.17 p3:

> The macros are […]

> >     offsetof(type, member-designator)

> which expands to an integer constant expression that has type `size_t` […]

combined with the noted property in C++11 that:

> "`offsetof` is required to work as specified even if unary `operator&` is overloaded for any of the types involved"

Therefore implementations should already be able without heroic efforts to realize this functionality by some intrinsic. The wording needs at least to ensure that for any lvalue core constant expression `e` the expression `std::addressof(e)` is a core constant expression.

[2013-09 Chicago]

[2014-06-08, Daniel improves wording]

It has been ensured that the wording is in sync with the recent working paper and the usage of "any" has been improved to say "every" instead (the fix is similar to that applied by LWG 2150).

Previous resolution from Daniel [SUPERSEDED]:

> 1. Change header `<memory>` synopsis, 20.7.2 [memory.syn] as indicated:

>    >     namespace std {
>    >       […]
>    >       // 20.7.12 [specialized.algorithms], specialized algorithms:
>    >       template <class T> constexpr T* addressof(T& r) noexcept;
>    >       […]
>    >     }

> 2. Change 20.7.12.1 [specialized.addressof] as indicated:

>    >     template <class T> constexpr T* addressof(T& r) noexcept;

>    > > -1- Returns: The actual address of the object or function referenced by `r`, even in the presence of an overloaded `operator&`.

>    > > -?- Remarks: For every lvalue core constant expression `e` (5.19 [expr.const]), the expression `std::addressof(e)` is a core constant expression.

[2014-06-09, further improvements]

A new wording form is now used similar to the approach used by LWG 2234, which is a stricter way to impose the necessary implementation requirements.

Proposed resolution:

This wording is relative to N3936.

1. Introduce the following new definition to the existing list in 17.3 [definitions]: [Drafting note: If LWG 2234 is accepted before this issue, the accepted wording for the new definition should be used instead — end drafting note]

   > constant subexpression [defns.const.subexpr]

   > an expression whose evaluation as subexpression of a conditional-expression CE (5.16 [expr.cond]) would not prevent CE from being a core constant expression (5.19 [expr.const]).

2. Change header `<memory>` synopsis, 20.7.2 [memory.syn] as indicated:

   >     namespace std {
   >       […]
   >       // 20.7.12 [specialized.algorithms], specialized algorithms:
   >       template <class T> constexpr T* addressof(T& r) noexcept;
   >       […]
   >     }

3. Change 20.7.12.1 [specialized.addressof] as indicated:

   >     template <class T> constexpr T* addressof(T& r) noexcept;

   > > -1- Returns: The actual address of the object or function referenced by `r`, even in the presence of an overloaded `operator&`.

   > > -?- Remarks: An expression `std::addressof(E)` is a constant subexpression ( [defns.const.subexpr]), if `E` is an lvalue constant subexpression.

### 2302. Passing null pointer to placement new

Section: 18.6.1.3 [new.delete.placement] Status: Tentatively NAD Submitter: Marc Glisse Opened: 2013-09-12 Last modified: 2014-05-02

View other active issues in [new.delete.placement].

View all other issues in [new.delete.placement].

View all issues with Tentatively NAD status.

Discussion:

Based on this discussion and as discussed in c++std-core-23998 and c++std-lib-34442, calling placement new currently forces the compiler to check if the pointer is null before initializing the object (a non-negligible cost). It seems many people were not aware of this and they consider it a user error to pass a null pointer to it.

Proposed resolution: for `operator new` and `operator new[]`, add:

> Requires: `ptr` shall not be a null pointer.

[2014-02-15 post-Issaquah session : move to Tentatively NAD]

AJM to supply the rationale...

Proposed resolution:

This wording is relative to N3691.

1. Change 18.6.1.3 [new.delete.placement] as indicated:

   >     void* operator new(std::size_t size, void* ptr) noexcept;

   > > -?- Requires: `ptr` shall not be a null pointer.

   > > -2- Returns: `ptr`.

   > > -3- Remarks: Intentionally performs no other action.

   > > -4- [Example: This can be useful for constructing an object at a known address:

   > > >     void* place = operator new(sizeof(Something));
   > > >     Something* p = new (place) Something();

   > > — end example]

   >     void* operator new[](std::size_t size, void* ptr) noexcept;

   > > -?- Requires: `ptr` shall not be a null pointer.

   > > -5- Returns: `ptr`.

   > > -6- Remarks: Intentionally performs no other action.

### 2303. Explicit instantiation of `std::vector<UserType>` broken?

Section: 18.6.1.3 [new.delete.placement] Status: New Submitter: Daniel Krügler Opened: 2013-09-18 Last modified: 2014-02-11

View other active issues in [new.delete.placement].

View all other issues in [new.delete.placement].

View all issues with New status.

Discussion:

The library gives explicit permission in 17.6.4.2.1 [namespace.std] p2 that user code may explicitly instantiate a library template provided that the instantiations depend on at least one user-defined type:

> A program may explicitly instantiate a template defined in the standard library only if the declaration depends on the name of a user-defined type and the instantiation meets the standard library requirements for the original template.

But it seems that the C++11 library is not specified in a way that guarantees such an instantiation to be well-formed if the minimum requirements of the library is not satisfied.

For example, in general, the first template parameter of `std::vector` is not required to be `DefaultConstructible` in general, but due to the split of the single C++03 member function with default argument

>     void resize(size_type sz, T c = T());

into

>     void resize(size_type sz);
>     void resize(size_type sz, const T& c);

the effect is now that for a type `ND` that is not `DefaultConstructible`, such as

>     struct NP {
>       NP(int);
>     };

the explicit instantiation of `std::vector<ND>` is no longer well-formed, because the attempt to instantiate the single-argument overload of `resize` cannot not succeed, because this function imposes the `DefaultInsertable` requirements and given the default allocator this effectively requires `DefaultConstructible`.

But `DefaultConstructible` is not the only point, what about `CopyConstructible` versus `MoveConstructible` alone? It turns out that currently the second `resize` overload would fail during an explicit instantiation for a type like

>     struct MO {
>       MO() = default;
>       MO(MO&&) = default;
>     };

because it imposes `CopyInsertable` requirements that end up being equivalent to the `CopyConstructible` requirements for the default allocator.

Technically a library can solve these issues: For special member functions by defining them in some base class, for others by transforming them effectively into a function template due to the great feature of default template arguments for function templates (At the very moment the validity of the latter approach depends on a resolution of core language issue CWG 1635, though). E.g. the here mentioned `resize` functions of `std::vector` could be prevented from instantiation by defining them like this with an implementation:

>     template<class = void>
>     void resize(size_type sz) { […] }
>     template<class = void>
>     void resize(size_type sz, const T& c) { […] }

In this case, these functions could also be defined in a base class, but the latter approach won't work in all cases.

Basically such an implementation is required to constrain all member functions that are not covered by the general requirements imposed on the actual library template parameters. I tested three different C++11 library implementations and but none could instantiate for example `std::list`, `std::vector`, or `std::deque` with value types that are not `DefaultConstructible` or only `MoveConstructible`.

This issue is raised to clarify the current situation in regard to the actual requirements imposed on user-provided types that are used to explicitly instantiate Library-provided templates. For example, the current Container requirements impose very little requirements on the actual value type and it is unclear to which extend library implementations have to respect that.

The minimum solution of this issue should be to at least realize that there is no fundamental requirement on `DefaultConstructible` for value types of library containers, because we have since C++03 the general statement of 17.6.3.1 [utility.arg.requirements] ("In general, a default constructor is not required."). It is unclear whether `CopyConstructible` should be required for an explicit instantiation request, but given the careful introduction of move operations in the library it would seem astonishing that a `MoveConstructible` type wouldn't suffice for value types of the container types.

In any case I can envision at least two approaches to solve this issue:

1. As indicated in LWG 2292, those function could get an explicit "Template Constraints:" element, albeit this promises more than needed to solve this issue.

2. The library could introduce a completely new element form, such as "Instantiation Constraints:" that would handle this situation for explicit instantiation situations. This would allow for simpler techniques to solve the issue when explicit instantiation is required compared to the first bullet, because it would not (necessarily) guarantee SFINAE-friendly expression-wellformedness, such as inspecting the expression `std::declval<std::vector<ND>&>.resize(0)` in an unevaluated context.

It should be noted that the 2013-08-27 comment to LWG 2193 could be resolved by a similar solution as indicated in this issue here.

Proposed resolution:

### 2307. Should the Standard Library use `explicit` only when necessary?

Section: 23 [containers] Status: New Submitter: Zhihao Yuan Opened: 2013-09-26 Last modified: 2014-02-11

View all other issues in [containers].

View all issues with New status.

Discussion:

LWG 2193 yields `explicit` for default ctors to allow `{}`, but not for all cases of uniform initialization. For example:

>     explicit vector(size_type count, const Allocator& alloc = Allocator());

This prevents `{n, alloc()}`. Although this use is relatively rare, but the behavior is inconsistent with that of

>     vector(size_type count, const T& value, const Allocator& alloc = Allocator());

Proposed resolution:

### 2309. `mutex::lock()` should not throw `device_or_resource_busy`

Section: 30.4.1.2 [thread.mutex.requirements.mutex] Status: New Submitter: Detlef Vollmann Opened: 2013-09-27 Last modified: 2014-06-19

View all other issues in [thread.mutex.requirements.mutex].

View all issues with New status.

Discussion:

As discussed during the Chicago meeting in SG1 the only reasonable reasons for throwing `device_or_resource_busy` seem to be:

- The thread currently already holds the mutex, the mutex is not recursive, and the implementation detects this. In this case `resource_deadlock_would_occur` should be thrown.

- Priority reasons. At least `std::mutex` (and possibly all standard mutex types) should not be setup this way, otherwise we have real problems with `condition_variable::wait()`.

[2014-06-17 Rapperswil]

Detlef provides wording

Proposed resolution:

This wording is relative to N3936.

1. Change 30.4.1.2 [thread.mutex.requirements.mutex] as indicated:

   > -13- Error conditions:

   > - `operation_not_permitted` — if the thread does not have the privilege to perform the operation.

   > - `resource_deadlock_would_occur` — if the implementation detects that a deadlock would occur.

   > - `device_or_resource_busy` — if the mutex is already locked and blocking is not possible.

### 2310. Public exposition only member in `std::array`

Section: 23.3.2.1 [array.overview] Status: New Submitter: Jonathan Wakely Opened: 2013-09-30 Last modified: 2014-02-11

View all issues with New status.

Discussion:

23.3.2.1 [array.overview] shows `std::array` with an "exposition only" data member, `elems`.

The wording in 17.5.2.3 [objects.within.classes] that defines how "exposition only" is used says it applies to private members, but `std::array::elems` (or its equivalent) must be public in order for `std::array` to be an aggregate.

If the intention is that `std::array::elems` places requirements on the implementation to provide "equivalent external behavior" to a public array member, then 17.5.2.3 [objects.within.classes] needs to cover public members too, or some other form should be used in 23.3.2.1 [array.overview].

Proposed resolution:

### 2312. `tuple`'s constructor constraints need to be phrased more precisely

Section: 20.4.2.1 [tuple.cnstr] Status: New Submitter: Stephan T. Lavavej Opened: 2013-09-21 Last modified: 2014-02-11

View all other issues in [tuple.cnstr].

View all issues with New status.

Discussion:

Consider the following code:

>     void meow(tuple<long, long>) { puts("Two"); }

>     void meow(tuple<long, long, long>) { puts("Three"); }

>     tuple<int, int, int> t(0, 0, 0);

>     meow(t);

This should compile and print "Three" because `tuple<long, long>`'s constructor from `const tuple<int, int, int>&` should remove itself from overload resolution. Implementations sensibly do this, but the Standard doesn't actually say it!

In this case, `Types` is "`long, long`" and `UTypes` is "`int, int, int`". 20.4.2.1 [tuple.cnstr]/3 says "let `i` be in the range `[0,sizeof...(Types))` in order", which is `[0, 2)`. Then /17 says "Remark: This constructor shall not participate in overload resolution unless `const Ui&` is implicitly convertible to `Ti` for all `i`." Interpreted literally, this is true! /15 says "Requires: `sizeof...(Types) == sizeof...(UTypes)`." but requiring the sizes to be identical doesn't help. Only the special phrase "shall not participate in overload resolution unless" mandates SFINAE/`enable_if` machinery.

The wording that we need is almost available in the Requires paragraphs, except that the Requires paragraphs say "`is_constructible`" while the Remark paragraphs say "is implicitly convertible", which is the correct thing for the SFINAE constraints to check. My proposed resolution is to unify the Requires and Remark paragraphs, after which there will be no need for Requires (when a constructor participates in overload resolution if and only if `X` is true, then there's no need for it to Require that `X` is true).

Note: 20.10.4.3 [meta.unary.prop]/6 specifies `is_constructible<To, From>` and 20.10.6 [meta.rel]/4 specifies `is_convertible<From, To>`. Both are specified in terms of "`template <class T> typename add_rvalue_reference<T>::type create();`". Therefore, passing `From` and `From&&` is equivalent, regardless of whether `From` is an object type, an lvalue reference, or an rvalue reference.

Also note that 20.4.2.1 [tuple.cnstr]/3 defines `T0` and `T1` so we don't need to repeat their definitions.

Proposed resolution:

This wording is relative to N3691.

1. Edit 20.4.2.1 [tuple.cnstr] as indicated:

   >     template <class... UTypes>
   >       explicit constexpr tuple(UTypes&&... u);

   > > -8- Requires: `sizeof...(Types) == sizeof...(UTypes)`. `is_constructible<Ti, Ui&&>::value` is true for all i.

   > > […]

   > > -10- Remark: This constructor shall not participate in overload resolution unless each type in `UTypes` is implicitly convertible to its corresponding type in `Types` `sizeof...(Types) == sizeof...(UTypes)` and both `is_constructible<Ti, Ui>::value` and `is_convertible<Ui, Ti>::value` are true for all i.

   > […]

   >     template <class... UTypes>
   >       constexpr tuple(const tuple<UTypes...>& u);

   > > -15- Requires: `sizeof...(Types) == sizeof...(UTypes)`. `is_constructible<Ti, const Ui&>::value` is true for all i.

   > > […]

   > > -17- Remark: This constructor shall not participate in overload resolution unless `const Ui&` is implicitly convertible to `Ti` `sizeof...(Types) == sizeof...(UTypes)` and both `is_constructible<Ti, const Ui&>::value` and `is_convertible<const Ui&, Ti>::value` are true for all i.

   >     template <class... UTypes>
   >       constexpr tuple(tuple<UTypes...>&& u);

   > > -18- Requires: `sizeof...(Types) == sizeof...(UTypes)`. `is_constructible<Ti, Ui&&>::value` is true for all i.

   > > […]

   > > -20- Remark: This constructor shall not participate in overload resolution unless each type in `UTypes` is implicitly convertible to its corresponding type in `Types` `sizeof...(Types) == sizeof...(UTypes)` and both `is_constructible<Ti, Ui>::value` and `is_convertible<Ui, Ti>::value` are true for all i.

   >     template <class U1, class U2> constexpr tuple(const pair<U1, U2>& u);

   > > -21- Requires: `sizeof...(Types) == 2`. `is_constructible<T0, const U1&>::value` is true for the first type `T0` in Types and `is_constructible<T1, const U2&>::value` is true for the second type `T1` in `Types`.

   > > […]

   > > -23- Remark: This constructor shall not participate in overload resolution unless `const U1&` is implicitly convertible to `T0` and `const U2&` is implicitly convertible to `T1` `sizeof...(Types) == 2 && is_constructible<T0, const U1&>::value && is_constructible<T1, const U2&>::value && is_convertible<const U1&, T0>::value && is_convertible<const U2&, T1>::value` is true.

   >     template <class U1, class U2> constexpr tuple(pair<U1, U2>&& u);

   > > -24- Requires: `sizeof...(Types) == 2`. `is_constructible<T0, U1&&>::value` is true for the first type `T0` in Types and `is_constructible<T1, U2&&>::value` is true for the second type `T1` in `Types`.

   > > […]

   > > -26- Remark: This constructor shall not participate in overload resolution unless `U1` is implicitly convertible to `T0` and `U2` is implicitly convertible to `T1` `sizeof...(Types) == 2 && is_constructible<T0, U1>::value && is_constructible<T1, U2>::value && is_convertible<U1, T0>::value && is_convertible<U2, T1>::value` is true.

### 2318. `basic_string`'s wording has confusing relics from the copy-on-write era

Section: 21.4 [basic.string] Status: New Submitter: Stephan T. Lavavej Opened: 2013-09-21 Last modified: 2014-02-11

View other active issues in [basic.string].

View all other issues in [basic.string].

View all issues with New status.

Discussion:

21.4.4 [string.capacity]/8 specifies `basic_string::resize(n, c)` with:

> Effects: Alters the length of the string designated by `*this` as follows:

> - If `n <= size()`, the function replaces the string designated by `*this` with a string of length `n` whose elements are a copy of the initial elements of the original string designated by `*this`.

> - If `n > size()`, the function replaces the string designated by `*this` with a string of length `n` whose first `size()` elements are a copy of the original string designated by `*this`, and whose remaining elements are all initialized to `c`.

This wording is a relic of the copy-on-write era. In addition to being extremely confusing, it has undesirable implications. Saying "replaces the string designated by `*this` with a string of length `n` whose elements are a copy" suggests that the trimming case can reallocate. Reallocation during trimming should be forbidden, like `vector`.

At least 7 paragraphs are affected: 21.4.4 [string.capacity]/8, 21.4.6.2 [string::append]/9, 21.4.6.3 [string::assign]/3 and /10, 21.4.6.4 [string::insert]/11, 21.4.6.5 [string::erase]/4, and 21.4.6.6 [string::replace]/11 say "replaces the string [designated/controlled] by `*this`". (21.4.6.7 [string::copy]/3 is different — it "replaces the string designated by `s`".)

Of the affected paragraphs, `resize()` and `erase()` are the most important to fix because they should forbid reallocation during trimming.

Proposed resolution:

### 2319. `basic_string`'s move constructor should not be `noexcept`

Section: 21.4.2 [string.cons] Status: Ready Submitter: Stephan T. Lavavej Opened: 2013-09-21 Last modified: 2014-03-03

View other active issues in [string.cons].

View all other issues in [string.cons].

View all issues with Ready status.

Discussion:

In debugging implementations, containers (including `basic_string`) may need to own dynamically allocated helper objects at all times, including in their default-constructed and moved-from states. This means that their default constructors and move constructors may throw exceptions. Therefore, the Standard should not mark them as `noexcept`. (Other implementations will still be permitted to add `noexcept`.)

[2014-02, Issaquah : move to Ready]

The issue discussion was highly controversial: The arguments in favour was that implementations exist that always need to allocate memory even for the move operations (similar as for some other containers) and that this cleans up an inconsistency between `std::string` and other container types. Counter arguments were that potentially throwing move operations reduce much of the advantages of move-support, e.g. in `vector<string>`.

straw poll: accept wording in the issue
SF 4 WF 4 N 0 WA 1 SA 1

straw poll: 14 or 17?
C++14: 4 C++17: 4

Move to Ready for C++17, as too close to 14 DIS without strong consensus.

It was suggested to introduce a special library vocabulary that specifies a "normative encouragement to not throw exceptions" for functions like these.

NJ: I offer to write a proposal to add encouragement for not throwing ... "`noexcept` in italics means should not throw"

Proposed resolution:

This wording is relative to N3691.

1. In 21.4 [basic.string]/5, class template `basic_string` synopsis, and 21.4.2 [string.cons]/2 change as indicated:

   >     basic_string(basic_string&& str) noexcept;

2. Edit 21.4.2 [string.cons]/17 as indicated:

   >     basic_string(const basic_string& str, const Allocator& alloc);
   >     basic_string(basic_string&& str, const Allocator& alloc);

   > > […]

   > > -17- Throws: The second form throws nothing if `alloc == str.get_allocator()`..

### 2321. Moving containers should (usually) be required to preserve iterators

Section: 23.2.1 [container.requirements.general] Status: Open Submitter: Stephan T. Lavavej Opened: 2013-09-21 Last modified: 2014-02-14

View other active issues in [container.requirements.general].

View all other issues in [container.requirements.general].

View all issues with Open status.

Discussion:

23.2.1 [container.requirements.general]/10 says that unless otherwise specified, "no `swap()` function invalidates any references, pointers, or iterators referring to the elements of the containers being swapped. [Note: The `end()` iterator does not refer to any element, so it may be invalidated. — end note]". However, move constructors and move assignment operators aren't given similar invalidation guarantees. The guarantees need several exceptions, so I do not believe that blanket language like /11 "Unless otherwise specified (either explicitly or by defining a function in terms of other functions), invoking a container member function or passing a container as an argument to a library function shall not invalidate iterators to, or change the values of, objects within that container." is applicable.

[2014-02-13 Issaquah]

General agreeement on intent, several wording nits and additional paragraphs to hit.

STL to provide updated wording. Move to Open.

Proposed resolution:

This wording is relative to N3691.

1. In 23.2.1 [container.requirements.general]/10 change as indicated:

   > -10- Unless otherwise specified (see 23.2.4.1, 23.2.5.1, 23.3.3.4, and 23.3.7.5) all container types defined in this Clause meet the following additional requirements:

   > - […]

   > - no copy constructor or assignment operator of a returned iterator throws an exception.

   > - no move constructor (or move assignment operator when `allocator_traits<allocator_type>::propagate_on_container_move_assignment::value` is true) of a container (except for `array`) invalidates any references, pointers, or iterators referring to the elements of the source container. [Note: The `end()` iterator does not refer to any element, so it may be invalidated. — end note]

   > - no `swap()` function throws an exception.

   > - no `swap()` function invalidates any references, pointers, or iterators referring to the elements of the containers being swapped. [Note: The `end()` iterator does not refer to any element, so it may be invalidated. — end note]

### 2325. `minmax_element()`'s behavior differing from `max_element()`'s should be noted

Section: 25.4.7 [alg.min.max] Status: Tentatively Ready Submitter: Stephan T. Lavavej Opened: 2013-09-21 Last modified: 2014-06-17

View other active issues in [alg.min.max].

View all other issues in [alg.min.max].

View all issues with Tentatively Ready status.

Discussion:

25.4.7 [alg.min.max]/23 says that `max_element()` finds the first biggest element, while /25 says that `minmax_element()` finds the last biggest element. This significant difference is unusual — it means that `minmax_element(args)` is not equivalent to `make_pair(min_element(args), max_element(args))`, whereas the other major "two for one" algorithm `equal_range(args)` is equivalent to `make_pair(lower_bound(args), upper_bound(args))`. `minmax_element()`'s behavior is intentional — it is a fundamental consequence of the `3N/2` algorithm — but the Standardese does not draw attention to this in any way. This wording came from LWG 715's resolution (which changed the semantics but didn't mention it), citing CLRS for the algorithm — but CLRS doesn't mention the behavior for equivalent elements! The wording here deeply confused me (as an STL maintainer fixing an incorrect implementation) until I walked through the algorithm by hand and figured out the fundamental reason. It would be really nice for the Standard to provide a hint that something magical is happening here.

[2014-06-06 Library reflector vote]

The issue has been identified as Tentatively Ready based on six votes in favour.

Proposed resolution:

This wording is relative to N3691.

1. Add a footnote to 25.4.7 [alg.min.max]/25 as indicated:

   >     template<class ForwardIterator>
   >       pair<ForwardIterator, ForwardIterator>
   >         minmax_element(ForwardIterator first, ForwardIterator last);
   >     template<class ForwardIterator, class Compare>
   >       pair<ForwardIterator, ForwardIterator>
   >         minmax_element(ForwardIterator first, ForwardIterator last, Compare comp);

   > > -25- Returns: `make_pair(first, first)` if `[first,last)` is empty, otherwise `make_pair(m, M)`, where `m` is the first iterator in `[first,last)` such that no iterator in the range refers to a smaller element, and where `M` is the last iterator [Footnote: This behavior intentionally differs from `max_element()`.] in `[first,last)` such that no iterator in the range refers to a larger element.

### 2326. `uniform_int_distribution<unsigned char>` should be permitted

Section: 26.5.1.1 [rand.req.genl] Status: New Submitter: Stephan T. Lavavej Opened: 2013-09-21 Last modified: 2014-02-11

View all issues with New status.

Discussion:

26.5.1.1 [rand.req.genl]/1 says: "Throughout this subclause 26.5, the effect of instantiating a template [...] that has a template type parameter named `IntType` is undefined unless the corresponding template argument is cv-unqualified and is one of `short`, `int`, `long`, `long long`, `unsigned short`, `unsigned int`, `unsigned long`, or `unsigned long long`." 26.5.8.2.1 [rand.dist.uni.int] specifies `template<class IntType = int> class uniform_int_distribution`, so this forbids `uniform_int_distribution<char/signed char/unsigned char>`.

I am not aware of anything in `<random>` that works with 16-bit integers but fails with 8-bit integers, so I suspect that `IntType` and `UIntType` could simply be extended to permit the `char` family. Alternatively, this change could be limited to `uniform_int_distribution` alone, where it is definitely safe. A `<random>` expert should decide which change is best.

Proposed resolution:

### 2328. Rvalue stream extraction should use perfect forwarding

Section: 27.7.2.6 [istream.rvalue] Status: Open Submitter: Stephan T. Lavavej Opened: 2013-09-21 Last modified: 2014-05-02

View all issues with Open status.

Discussion:

27.7.2.6 [istream.rvalue] declares `operator>>(basic_istream<charT, traits>&& is, T& x)`. However, 27.7.2.2.3 [istream::extractors]/7 declares `operator>>(basic_istream<charT,traits>& in, charT* s)`, plus additional overloads for `unsigned char*` and `signed char*`. This means that "`return_rvalue_istream() >> &arr[0]`" won't compile, because `T&` won't bind to the rvalue `&arr[0]`.

[2014-02-12 Issaquah : recategorize as P3]

Jonathan Wakely: Bill was certain the change is right, I think so with less certainty

Jeffrey Yaskin: I think he's right, hate that we need this

Jonathan Wakely: is this the security issue Jeffrey raised on lib reflector?

Move to P3

Proposed resolution:

This wording is relative to N3691.

1. Edit 27.7.1 [iostream.format.overview], header `<istream>` synopsis, as indicated:

   >     namespace std {
   >       […]
   >       template <class charT, class traits, class T>
   >         basic_istream<charT, traits>&
   >         operator>>(basic_istream<charT, traits>&& is, T&& x);
   >     }

2. Edit 27.7.2.6 [istream.rvalue] as indicated:

   >     template <class charT, class traits, class T>
   >       basic_istream<charT, traits>&
   >       operator>>(basic_istream<charT, traits>&& is, T&& x);

   > > -1- Effects: `is >>x std::forward<T>(x)`

   > > -2- Returns: `is`

### 2331. `regex_constants::collate`'s effects are inaccurately summarized

Section: 28.5.1 [re.synopt] Status: Open Submitter: Stephan T. Lavavej Opened: 2013-09-21 Last modified: 2014-05-23

View all other issues in [re.synopt].

View all issues with Open status.

Discussion:

The table in 28.5.1 [re.synopt]/1 says that `regex_constants::collate` "Specifies that character ranges of the form "`[a-b]`" shall be locale sensitive.", but 28.13 [re.grammar]/14 says that it affects individual character comparisons too.

[2012-02-12 Issaquah : recategorize as P3]

Marshall Clow: 28.13/14 only applies to ECMAScript

All: we're unsure

Jonathan Wakely: we should ask John Maddock

Move to P3

Proposed resolution:

This wording is relative to N3691.

1. In 28.5.1 [re.synopt]/1, Table 138 — "`syntax_option_type` effects", change as indicated:

   > Table 138 — `syntax_option_type` effects
   > Element | Effect(s) if set
   > --- | ---
   > `…`
   > `collate` | Specifies that character ranges of the form "`[a-b]`"comparisons and character range comparisons shall be locale sensitive.
   > `…`

### 2334. `atomic`'s default constructor requires "uninitialized" state even for types with non-trivial default-constructor

Section: 29.6.5 [atomics.types.operations.req] Status: New Submitter: Daniel Krügler Opened: 2013-10-03 Last modified: 2014-05-23

View all other issues in [atomics.types.operations.req].

View all issues with New status.

Discussion:

According to 29.6.5 [atomics.types.operations.req] p4,

>     A ::A () noexcept = default;

> > Effects: leaves the atomic object in an uninitialized state. [Note: These semantics ensure compatibility with `C`. — end note]

This implementation requirement is OK for POD types, like `int`, but 29.5 [atomics.types.generic] p1 intentionally allows template arguments of `atomic` with a non-trivial default constructor ("The type of the template argument `T` shall be trivially copyable (3.9)"), so this wording can be read in a way that makes the behaviour of the following code undefined:

>     #include <atomic>
>     #include <iostream>

>     struct S {
>       S() noexcept : v(42) {}
>       int v;
>     };

>     int main() {
>       std::atomic<S> as; // Default-initialization
>       std::cout << as.load().v << std::endl; // ?
>     }

For a user-defined emulation of `atomic` the expected outcome would be defined and the program would output "42", but existing implementations differ and the result value is a "random number" for at least one implementation. This seems very surprising to me.

To realize that seemingly existing requirement, an implementation is either required to violate normal language rules internally or to perform specific bit-randomization-techniques after the normal default-initialization that called the default constructor of `S`.

According to my understanding, the non-normative note in 29.6.5 [atomics.types.operations.req] p4 is intended to refer to types that are valid `C`-types, but the example type `S` is not such a type.

To make the mental model of `atomic`'s default constructor more intuitive for user-code, I suggest to clarify the wording to have the effects of default-initialization instead. The current state seems more like an unintended effect of imprecise language used here and has some similarities to wording that was incorrectly used to specify `atomic_flag` initialization as described by LWG 2159.

[2014-05-17, Daniel comments and provides alternative wording]

The current wording was considered controversial as expressed by reflector discussions. To me, the actual problem is not newly introduced by that wording, but instead is already present in basically all paragraphs specifying semantics of atomic types, since the wording never clearly distinguishes the value of the actual atomic type A and the value of the "underlying", corresponding non-atomic type C. The revised proposed wording attempts to improve the current ambiguity of these two kinds of values.

Previous resolution from Daniel [SUPERSEDED]:

> This wording is relative to N3691.

> 1. Modify 29.6.5 [atomics.types.operations.req] p4 as indicated: [Editorial note: There is no exposition-only member in `atomic`, which makes it a bit hard to specify what actually is initialized, but the usage of the term "value" seems consistent with similar wording used to specify the effects of the atomic `load` functions]

>    >     A ::A () noexcept = default;

>    > > -4- Effects: leaves the atomic object in an uninitialized state The value of the atomic object is default-initialized (8.5 [dcl.init]). [Note: These semantics ensure compatibility with `C`. — end note]

Proposed resolution:

This wording is relative to N3936.

1. Modify 29.6.5 [atomics.types.operations.req] p2 as indicated: [Editorial note: This is a near-to editorial change not directly affecting this issue, but `atomic_address` does no longer exist and the pointed to definition is relevant in the context of this issue resolution.]

   > -2- In the following operation definitions:

   > - an A refers to one of the atomic types.

   > - a C refers to its corresponding non-atomic type. The `atomic_address` atomic type corresponds to the `void*` non-atomic type.

   > - […]

2. Modify 29.6.5 [atomics.types.operations.req] p4 and the following as indicated: [Editorial note: There is no exposition-only member in `atomic`, which makes it a bit hard to specify what actually is initialized, but the introductory wording of 29.6.5 [atomics.types.operations.req] p2 b2 defines: "a C refers to its corresponding non-atomic type." which helps to specify the semantics in terms of "the C value referred to by the atomic object"]

   >     A::A() noexcept = default;

   > > -4- Effects: leaves the atomic object in an uninitialized state Default-initializes (8.5 [dcl.init]) the C value referred to by the atomic object. [Note: These semantics ensure compatibility with `C`. — end note]

   >     constexpr A::A(C desired) noexcept;

   > > -5- Effects: Direct-i Initializes the C value referred to by the atomic object with the value `desired`. Initialization is not an atomic operation (1.10). […]

   > > […]

   >     void atomic_init(volatile A* object, C desired) noexcept;
   >     void atomic_init(A* object, C desired) noexcept;

   > > -8- Effects: Non-atomically initializes the C value referred to by `*object` with value `desired`. […]

   >     void atomic_store(volatile A* object, C desired) noexcept;
   >     […]
   >     void A::store(C desired, memory_order order = memory_order_seq_cst) noexcept;

   > > -9- […]

   > > -10- Effects: Atomically replaces the C value pointed to by `object` or by `this` with the value of `desired`. […]

   > > […]

   >     C atomic_load(const volatile A* object) noexcept;
   >     […]
   >     C A::load(memory_order order = memory_order_seq_cst) const noexcept;

   > > -13- […]

   > > -14- […]

   > > -15- Returns: Atomically returns the C value pointed to by `object` or by `this`.

   > > […]

   >     C atomic_exchange(volatile A* object, C desired) noexcept;
   >     […]
   >     C A::exchange(C desired, memory_order order = memory_order_seq_cst) noexcept;

   > > -18- Effects: Atomically replaces the C value pointed to by `object` or by `this` with `desired`. […]

   > > -19- Returns: Atomically returns the C value pointed to by `object` or by `this` immediately before the effects.

   > > […]

   >     C atomic_fetch_key(volatile A* object, M operand) noexcept;
   >     […]
   >     C A::fetch_key(M operand, memory_order order = memory_order_seq_cst) noexcept;

   > > -28- Effects: Atomically replaces the C value pointed to by `object` or by `this` with the result of the computation applied to the C value pointed to by `object` or by `this` and the given `operand`. […]

   > > -29- Returns: Atomically, returns the C value pointed to by `object` or by `this` immediately before the effects.

   > > […]

3. Modify 29.7 [atomics.flag] p5 and the following as indicated:

   >     bool atomic_flag_test_and_set(volatile atomic_flag* object) noexcept;
   >     […]
   >     bool atomic_flag::test_and_set(memory_order order = memory_order_seq_cst) noexcept;

   > > -5- Effects: Atomically sets the bool value pointed to by `object` or by `this` to `true`. […]

   > > -6- Returns: Atomically, returns the bool value of the pointed to by `object` or by `this` immediately before the effects.

   >     void atomic_flag_clear(volatile atomic_flag* object) noexcept;
   >     […]
   >     void atomic_flag::clear(memory_order order = memory_order_seq_cst) noexcept;

   > > -7- […]

   > > -8- Effects: Atomically sets the bool value pointed to by `object` or by `this` to `false`. […]

### 2335. `array<array<int, 3>, 4>` should be layout-compatible with `int[4][3]`

Section: 23.3.2 [array] Status: New Submitter: Jeffrey Yasskin Opened: 2013-10-04 Last modified: 2014-02-11

View all other issues in [array].

View all issues with New status.

Discussion:

In order to replace some uses of C arrays with `std::array`, we need it to be possible to cast from a `std::array<>` to an equivalent C array. Core wording doesn't appear to be in quite the right state to allow casting, but if we specify that appropriate types are layout-compatible, we can at least write:

>     union {
>       array<array<array<int, 2>, 3>, 4> arr;
>       int carr[4][3][2];
>     };

to view memory as the other type: C++14 CD [class.mem]p18.

I believe it's sufficient to add "`array<T, N>` shall be layout-compatible (3.9 [basic.types]) with `T[N]`." to 23.3.2.1 [array.overview], but we might also need some extension to 9.2 [class.mem] to address the possibility of layout-compatibility between struct and array types.

I checked that libc++ on MacOS already implements this, although it would be good for someone else to double-check; I haven't checked any other standard libraries.

Proposed resolution:

### 2336. `is_trivially_constructible/is_trivially_assignable` traits are always false

Section: 20.10.4.3 [meta.unary.prop] Status: New Submitter: Daniel Krügler Opened: 2013-10-01 Last modified: 2014-06-17

View other active issues in [meta.unary.prop].

View all other issues in [meta.unary.prop].

View all issues with New status.

Discussion:

In 20.10.4.3 [meta.unary.prop] we have traits to allow testing for triviality of specific operations, such as `is_trivially_constructible` and `is_trivially_assignable` (and their derived forms), which are specified in terms of the following initialization and assignment, respectively:

>     T t(create<Args>()...);

>     declval<T>() = declval<U>()

The wording that describes the way how triviality is deduced, is in both cases of the same form:

> [… ] and the variable definition/assignment, as defined by `is_constructible/is_assignable`, is known to call no operation that is not trivial (3.9, 12).

The problematic part of this wording is that both definitions are specified in terms of an "object construction" function `create` or `declval`, respectively, (The former being a conceptual function, the latter being a library function), but for none of these functions we can assume that they could be considered as trivial — only special member functions can have this property and none of these is one. This problem became obvious, when the similar issue LWG 2298 in regard to `is_nothrow_constructible` was opened.

A possible approach to solve this specification problem is to make a blanket statement for sub-clause 20.10.4.3 [meta.unary.prop] that these helper functions are considered trivial for the purpose of defining these traits.

Using this kind of wording technique can also be used to get rid of the additional helper function template `create`, which is currently needed for the `is_convertible` and the `is_constructible` traits, because both traits are specified in terms of contexts where technically the corresponding "object construction" function would be considered as odr-used. This is problematic, because these traits are defined in terms of well-formed code and odr-using `declval` would make the program ill-formed (see 20.2.5 [declval]). So extending above blanket statement to consider `std::declval<T>()` as not odr-used in the context of the corresponding trait definition would allow for replacing `create` by `declval`.

Proposed resolution:

This wording is relative to N3936.

1. Add a new paragraph after 20.10.4.3 [meta.unary.prop] p3 as indicated: [Editorial note: The first change in 20.10.4.3 [meta.unary.prop] p3 is recommended, because technically a Clause is always a "main chapter" — such as Clause 20 — but every child of a Clause or sub-clause is a sub-clause]

   > […]

   > -3- For all of the class templates `X` declared in this Clause sub-clause, instantiating that template with a template-argument that is a class template specialization may result in the implicit instantiation of the template argument if and only if the semantics of `X` require that the argument must be a complete type.

   > -?- For the purpose of defining the templates in this sub-clause, a function call expression `declval<T>()` for any type `T` is considered to be a trivial (3.9 [basic.types], 12 [special]) function call that is not an odr-use (3.2 [basic.def.odr]) of `declval` in the context of the corresponding definition notwithstanding the restrictions of 20.2.5 [declval].

   > […]

2. Modify 20.10.4.3 [meta.unary.prop] p7 as indicated:

   > -7- Given the following function prototype:

   > >     template <class T>
   > >       typename add_rvalue_reference<T>::type create();

   > t The predicate condition for a template specialization `is_constructible<T, Args...>` shall be satisfied if and only if the following variable definition would be well-formed for some invented variable `t`:

   > >     T t(createdeclval<Args>()...);

   > […]

3. Add a new paragraph after 20.10.6 [meta.rel] p2 as indicated: [Editorial note: Technically we don't need the guarantee of "a trivial function call" for the type relationship predicates at the very moment, but it seems more robust and consistent to have the exact same guarantee here as well]

   > […]

   > -2- […]

   > -?- For the purpose of defining the templates in this sub-clause, a function call expression `declval<T>()` for any type `T` is considered to be a trivial (3.9 [basic.types], 12 [special]) function call that is not an odr-use (3.2 [basic.def.odr]) of `declval` in the context of the corresponding definition notwithstanding the restrictions of 20.2.5 [declval].

   > […]

4. Modify 20.10.6 [meta.rel] p4 as indicated:

   > -4- Given the following function prototype:

   > >     template <class T>
   > >       typename add_rvalue_reference<T>::type create();

   > t The predicate condition for a template specialization `is_convertible<From, To>` shall be satisfied if and only if the return expression in the following code would be well-formed, including any implicit conversions to the return type of the function:

   > >     To test() {
   > >       return createdeclval<From>();
   > >     }

   > […]

### 2337. `shared_ptr operator*()` should not be `noexcept`

Section: 20.8.2.2.5 [util.smartptr.shared.obs] Status: New Submitter: Stephan T. Lavavej Opened: 2013-10-05 Last modified: 2014-03-03

View all other issues in [util.smartptr.shared.obs].

View all issues with New status.

Discussion:

20.8.1.2.4 [unique.ptr.single.observers]/3: "`pointer operator->() const noexcept;` Requires: `get() != nullptr`."

20.8.2.2.5 [util.smartptr.shared.obs]/2: "`T& operator*() const noexcept;` Requires: `get() != 0`."

20.8.2.2.5 [util.smartptr.shared.obs]/5: "`T* operator->() const noexcept;` Requires: `get() != 0`."

Narrow-contract functions should not be `noexcept`.

[2015-02-15 Issuquah]

Issue is contentious, raise to P2.

Proposed resolution:

This wording is relative to N3691.

1. In 20.8.1.2 [unique.ptr.single]/1, class template `unique_ptr` synopsis for single objects, change as indicated:

   >     pointer operator->() const noexcept;

2. In 20.8.1.2.4 [unique.ptr.single.observers] change as indicated:

   >     pointer operator->() const noexcept;

   > > -3- Requires: `get() != nullptr`.

   > > -4- Returns: `get()`.

   > > -?- Throws: Nothing.

   > > -5- Note: use typically requires that `T` be a complete type.

3. In 20.8.2.2 [util.smartptr.shared]/1, class template `shared_ptr` synopsis, change as indicated:

   >     T& operator*() const noexcept;
   >     T* operator->() const noexcept;

4. In 20.8.2.2.5 [util.smartptr.shared.obs] change as indicated:

   >     T& operator*() const noexcept;

   > > -2- Requires: `get() != 0`.

   > > -3- Returns: `*get()`.

   > > -?- Throws: Nothing.

   > > -4- Remarks: When `T` is `void`, it is unspecified whether this member function is declared. If it is declared, it is unspecified what its return type is, except that the declaration (although not necessarily the definition) of the function shall be well formed.

   >     T* operator->() const noexcept;

   > > -5- Requires: `get() != 0`.

   > > -6- Returns: `get()`.

   > > -?- Throws: Nothing.

### 2338. [re.traits]/7 expects of locale facets something not guaranteed by [locale.facet]/4

Section: 28.7 [re.traits], 22.3.1.1.2 [locale.facet] Status: New Submitter: Sergey Zubkov Opened: 2013-10-15 Last modified: 2014-02-11

View all other issues in [re.traits].

View all issues with New status.

Discussion:

28.7 [re.traits]/7, begins with "if `typeid(use_facet<collate<charT> >) == typeid(collate_byname<charT>)`", which appears to be pseudocode with the intention to convey that the collate facet has not been replaced by the user. Cf. the wording in N1429 "there is no portable way to implement `transform_primary` in terms of `std::locale`, since even if the sort key format returned by `std::collate_byname<>::transform` is known and can be converted into a primary sort key, the user can still install their own custom `std::collate` implementation into the locale object used, and that can use any sort key format they see fit.".

Taken literally, 28.7 [re.traits]/7 appears to imply that named locales are required to hold their collate facets with dynamic type `std::collate_byname<charT>`, which is in fact true in some implementations (e.g libc++), but not others (e.g. libstdc++). This does not follow from the description of `_byname` in 22.3.1.1.2 [locale.facet]/4, which is only required to provide equivalent semantics, to the named locale's facet, not to actually be one.

Proposed resolution:

This wording is relative to N3691.

1. Modify 22.3.1.1.2 [locale.facet]/4 as indicated:

   > For some standard facets a standard "...`_byname`" class, derived from it, implements the virtual function semantics equivalent to provided by that facet of the locale constructed by `locale(const char*)` with the same name. Each such facet provides a constructor that takes a `const char*` argument, which names the locale, and a `refs` argument, which is passed to the base class constructor. Each such facet also provides a constructor that takes a string argument `str` and a `refs` argument, which has the same effect as calling the first constructor with the two arguments `str.c_str()` and `refs`. If there is no "...`_byname`" version of a facet, the base class implements named locale semantics itself by reference to other facets. For any locale `loc` constructed by `locale(const char*)` and facet `Facet` that has a corresponding standard `Facet_byname` class, `typeid(use_facet<Facet>(loc)) == typeid(Facet_byname)`.

2. Modify 28.7 [re.traits]/7 as indicated:

   >     template <class ForwardIterator>
   >       string_type transform_primary(ForwardIterator first, ForwardIterator last) const;

   > > -7- Effects: if `typeid(use_facet<collate<charT> >(getloc())) == typeid(collate_byname<charT>)` and the form of the sort key returned by `collate_byname<charT>::transform(first, last)` is known and can be converted into a primary sort key then returns that key, otherwise returns an empty string.

### 2340. Replacement allocation functions declared as inline

Section: 17.6.4.6 [replacement.functions] Status: Ready Submitter: David Majnemer Opened: 2013-10-20 Last modified: 2014-03-03

View all other issues in [replacement.functions].

View all issues with Ready status.

Discussion:

N3290 17.6.4.6 [replacement.functions]/p3 says:

> The program's definitions shall not be specified as `inline`.

This seems to permit declarations of replacement allocation functions that are specified as `inline` so long as they aren't used. This behavior seems more like a bug than a feature, I propose that we do the following:

> The program's definitions declarations shall not be specified as `inline`.

[2014-02-15 Issaquah : Move to Ready]

Proposed resolution:

This wording is relative to N3797.

1. Modify 17.6.4.6 [replacement.functions]/3 as indicated:

   > -3- The program's definitions are used instead of the default versions supplied by the implementation (18.6). Such replacement occurs prior to program startup (3.2, 3.6). The program's definitions declarations shall not be specified as `inline`. No diagnostic is required.

### 2342. User conversion to `wchar_t const*` or to `wchar_t` not invoked for `operator<<`

Section: 27.7.3.1 [ostream] Status: New Submitter: Alf P. Steinbach Opened: 2013-10-29 Last modified: 2014-02-11

View all other issues in [ostream].

View all issues with New status.

Discussion:

For wide streams argument types `wchar_t const*` and `wchar_t` are supported only as template parameters. User defined conversions are not considered for template parameter matching. Hence inappropriate overloads of `operator<<` are selected when an implicit conversion is required for the argument, which is inconsistent with the behavior for `char const*` and `char`, is unexpected, and is a useless result.

Demonstration:

>     #include <iostream>

>     struct Byte_string
>     {
>       operator char const*() const { return "Hurray, it works!"; }
>     };

>     struct Wide_string
>     {
>       operator wchar_t const*() const { return L"Hurray, it works!"; }
>     };

>     struct Byte_ch
>     {
>       operator char() const { return 'X'; }
>     };

>     struct Wide_ch
>     {
>       operator wchar_t() const { return L'X'; }
>     };

>     auto main() -> int
>     {
>       using namespace std;
>       wcout << "'X' as char value   : " << Byte_ch() << endl;
>       wcout << "'X' as wchar_t value: " << Wide_ch() << endl;
>       wcout << "Byte string pointer : " << Byte_string() << endl;
>       wcout << "Wide string pointer : " << Wide_string() << endl;
>     }

Example output:

>     'X' as char value   : X
>     'X' as wchar_t value: 88
>     Byte string pointer : Hurray, it works!
>     Wide string pointer : 000803C8

Proposed resolution:

This wording is relative to N3797.

1. Modify 27.7.3.1 [ostream], class template `basic_ostream` synopsis, as indicated:

   >     namespace std {
   >     […]

   >     // 27.7.3.6.4 character inserters
   >     template<class charT, class traits>
   >       basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,
   >                                               charT);
   >     template<class charT, class traits>
   >       basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,
   >                                               char);
   >     template<class traits>
   >       basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&,
   >                                              char);
   >     template<class traits>
   >       basic_ostream<wchar_t,traits>& operator<<(basic_ostream<wchar_t,traits>&,
   >                                                 wchar_t);
   >     […]

   >     template<class charT, class traits>
   >       basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,
   >                                               const charT*);
   >     template<class charT, class traits>
   >       basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,
   >                                               const char*);
   >     template<class traits>
   >       basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&,
   >                                              const char*);
   >     template<class traits>
   >       basic_ostream<wchar_t,traits>& operator<<(basic_ostream<wchar_t,traits>&,
   >                                                 const wchar_t*);
   >     […]
   >     }

2. Modify 27.7.3.6.4 [ostream.inserters.character] as indicated: [Drafting note: The replacement of `os` by `out` in p1 and the insertion of "`out.`" in p4 just fix two obvious typos — end drafting note]

   >     template<class charT, class traits>
   >       basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& out,
   >                                               charT c);
   >     template<class charT, class traits>
   >       basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& out,
   >                                               char c);
   >     // specialization
   >     template<class traits>
   >       basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out,
   >                                              char c);
   >     template<class traits>
   >       basic_ostream<wchar_t,traits>& operator<<(basic_ostream<wchar_t,traits>& out,
   >                                                 wchar_t c);

   >     // signed and unsigned
   >     template<class traits>
   >       basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out,
   >                                               signed char c);
   >     template<class traits>
   >       basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out,
   >                                               unsigned char c);

   > > -1- Effects: Behaves as a formatted output function (27.7.3.6.1 [ostream.formatted.reqmts]) of `out`. Constructs a character sequence `seq`. If `c` has type `char` and the character type of the stream is not `char`, then `seq` consists of `out.widen(c)`; otherwise `seq` consists of `c`. Determines padding for `seq` as described in 27.7.3.6.1 [ostream.formatted.reqmts]. Inserts `seq` into `out`. Calls `osout.width(0)`.

   > > -2- Returns: `out`.

   >     template<class charT, class traits>
   >       basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& out,
   >                                               const charT* s);
   >     template<class charT, class traits>
   >       basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& out,
   >                                               const char* s);
   >     template<class traits>
   >       basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out,
   >                                              const char* s);
   >     template<class traits>
   >       basic_ostream<wchar_t,traits>& operator<<(basic_ostream<wchar_t,traits>& out,
   >                                                 const wchar_t* s);

   >     template<class traits>
   >       basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out,
   >                                              const signed char* s);
   >     template<class traits>
   >       basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out,
   >                                              const unsigned char* s);

   > > -3- Requires: `s` shall not be a null pointer.

   > > -4- Effects: Behaves like a formatted inserter (as described in 27.7.3.6.1 [ostream.formatted.reqmts]) of `out`. Creates a character sequence `seq` of `n` characters starting at `s`, each widened using `out.widen()` (27.5.5.3), where `n` is the number that would be computed as if by:

   > > - `traits::length(s)` for the following overloads:

   > >   - where the first argument is of type `basic_ostream<charT, traits>&` and the second is of type `const charT*`,

   > >   - and also for the overload where the first argument is of type `basic_ostream<char, traits>&` and the second is of type `const char*`,

   > >   - where the first argument is of type `basic_ostream<wchar_t, traits>&` and the second is of type `const wchar_t*`,

   > > - `std::char_traits<char>::length(s)` for the overload where the first argument is of type `basic_ostream<charT, traits>&` and the second is of type `const char*`,

   > > - `traits::length(reinterpret_cast<const char*>(s))` for the other two overloads.

   > > Determines padding for `seq` as described in 27.7.3.6.1 [ostream.formatted.reqmts]. Inserts `seq` into `out`. Calls `out.width(0)`.

   > > -5- Returns: `out`.

### 2343. Is the value of the ECMA-262 RegExp object's multiline property really false?

Section: 28.13 [re.grammar] Status: New Submitter: Nayuta Taga Opened: 2013-10-30 Last modified: 2014-02-11

View all other issues in [re.grammar].

View all issues with New status.

Discussion:

In the following "Multiline" is the value of the ECMA-262 RegExp object's multiline property.

In ECMA-262, there are some definitions that relate to Multiline:

- ECMA-262 15.10.2.6:

  > If Multiline is true, ^ matches just after LineTerminator.

  > If Multiline is false, ^ does not match just after LineTerminator.

  > If Multiline is true, $ matches just before LineTerminator.

  > If Multiline is false, $ does not match just before LineTerminator.

- ECMA-262 15.10.4.1, 15.10.7.4:

  > By default, Multiline is false.

So, the C++11 standard says that Multiline is false. As it is false, ^ matches only the beginning of the string, and $ matches only the end of the string.

However, two flags are defined in 28.5.2 [re.matchflag] Table 139:

> `match_not_bol`: the character ^ in the regular expression shall not match `[first,first)`.

> `match_not_eol`: the character "$" in the regular expression shall not match `[last,last)`.

As Multiline is false, the `match_not_bol` and the `match_not_eol` are meaningless because they only make ^ and $ match none.

In my opinion, Multiline should be true.

FYI, Multiline of the existing implementations are as follows:

Multiline=false:

- libstdc++ r206594

- libc++ r199174

Multiline=true:

- Visual Studio Express 2013

- boost 1.55

Proposed resolution:

### 2348. `charT('1')` is not the wide equivalent of `'1'`

Section: 20.6 [template.bitset], 27.7.6 [quoted.manip] Status: New Submitter: Zhihao Yuan Opened: 2013-12-02 Last modified: 2014-02-11

View all other issues in [template.bitset].

View all issues with New status.

Discussion:

Example: `char16_t('1') != u'1'` is possible.

The numeric value of `char16_t` is defined to be Unicode code point, which is same to the ASCII value and UTF-8 for 7-bit chars. However, `char` is not guaranteed to have an encoding which is compatible with ASCII. For example, `'1'` in EBCDIC is 241.

I found three places in the standard casting narrow char literals: `bitset::bitset`, `bitset::to_string` and `quoted`.

PJ confirmed this issue and says he has a solution used in their `<filesystem>` implementation, and he may want to propose it to the standard.

The solution in my mind, for now, is to make those default arguments magical, where the "magic" can be implemented with a C11 `_Generic` selection (works in clang):

>     #define _G(T, literal) _Generic(T{}, \
>           char: literal, \
>           wchar_t: L ## literal, \
>           char16_t: u ## literal, \
>           char32_t: U ## literal)

>       _G(char16_t, '1') == u'1'

Proposed resolution:

This wording is relative to N3797.

[Drafting note: This is a sample wording fixing only one case; I'm just too lazy to copy-paste it before we discussed whether the solution is worth and sufficient (for example, should the other `charT`s like `unsigned char` just don't compile without supplying those arguments? I hope so). — end drafting note]

1. Modify 20.6 [template.bitset] p1, class template `bitset` synopsis, as indicated:

   >     namespace std {
   >       template <size_t N> class bitset {
   >       public:
   >         […]
   >         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')see below, charT one = charT('1')see below);
   >          […]
   >       };
   >       […]
   >     }

2. Modify 20.6.1 [bitset.cons] as indicated:

   >     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')see below, charT one = charT('1')see below);

   > > -?- The default values of `zero` and `one` compare equal to the character literals `0` and `1` of type `charT`, respectively.

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

   > > […]

### 2349. Clarify input/output function rethrow behavior

Section: 27.7.2.2.1 [istream.formatted.reqmts] Status: New Submitter: Zhihao Yuan Opened: 2013-12-06 Last modified: 2014-02-11

View all other issues in [istream.formatted.reqmts].

View all issues with New status.

Discussion:

The formatted input function requirement says in 27.7.2.2.1 [istream.formatted.reqmts]:

> "If an exception is thrown during input then `ios::badbit` is turned on in `*this`'s error state. If `(exceptions()&badbit) != 0` then the exception is rethrown."

while some formatted function may throw an exception from `basic_ios::clear`, for example in 20.6.4 [bitset.operators] p6:

> "If no characters are stored in `str`, calls `is.setstate(ios_base::failbit)` (which may throw `ios_base::failure`)"

So should this exception be considered as "an exception [...] thrown during input"? And here is an implementation divergence (or you can read the following as "a bug libc++ only has" :)

>     cin.exceptions(ios_base::failbit);
>     bitset<N> b;
>     try {
>       cin >> b;  // type 'a' and return
>     } catch (...)
>     {}

Now `cin.rdstate()` is just `failbit` in libstdc++ (and Dinkumware, by PJ), but `failbit & badbit` libc++. Similar difference found in other places, like `eofbit & badbid` after `std::getline`.

PJ and Matt both agree that the intention (of `badbit` + rethrow) is "to signify an exception arising in user code, not the iostreams package".

In addition, I found the following words in unformatted input function's requirements (27.7.2.3 [istream.unformatted]):

> If an exception is thrown during input then `ios::badbit` is turned on in `*this`'s error state. (Exceptions thrown from `basic_ios<>::clear()` are not caught or rethrown.) If `(exceptions()&badbit) != 0` then the exception is rethrown.

The content within the parenthesis is added by LWG defect 61, and does fix the ambiguity. However, it only fixed the 1 of 4 requirements, and it lost some context (the word "rethrown" is not seen before this sentence within this section).

Proposed resolution:

This wording is relative to N3797.

[Drafting note: The editor is kindly asked to introduce additional spaces at the following marked occurrences of `operator&` — end drafting note]

1. Modify 27.7.2.2.1 [istream.formatted.reqmts] p1 as indicated:

   > -1- Each formatted input function begins execution by constructing an object of class `sentry` with the `noskipws` (second) argument false. If the `sentry` object returns true, when converted to a value of type `bool`, the function endeavors to obtain the requested input. If an exception, other than the ones thrown from `clear()`, if any, is thrown during input then `ios::badbit` is turned on[Footnote 314] in `*this`'s error state. If `(exceptions() & badbit) != 0` then the exception is rethrown. In any case, the formatted input function destroys the `sentry` object. If no exception has been thrown, it returns `*this`.

2. Modify 27.7.3.6.1 [ostream.formatted.reqmts] p1 as indicated:

   > -1- Each formatted output function begins execution by constructing an object of class `sentry`. If this object returns true when converted to a value of type `bool`, the function endeavors to generate the requested output. If the generation fails, then the formatted output function does `setstate(ios_base::failbit)`, which might throw an exception. If an exception, other than the ones thrown from `clear()`, if any, is thrown during output, then `ios::badbit` is turned on[Footnote 327] in `*this`'s error state. If `(exceptions() & badbit) != 0` then the exception is rethrown. Whether or not an exception is thrown, the `sentry` object is destroyed before leaving the formatted output function. If no exception is thrown, the result of the formatted output function is `*this`.

3. Modify 27.7.3.7 [ostream.unformatted] p1 as indicated:

   > -1- Each unformatted output function begins execution by constructing an object of class `sentry`. If this object returns true, while converting to a value of type `bool`, the function endeavors to generate the requested output. If an exception, other than the ones thrown from `clear()`, if any, is thrown during output, then ios::badbit is turned on[Footnote 330] in `*this`'s error state. If `(exceptions() & badbit) != 0` then the exception is rethrown. In any case, the unformatted output function ends by destroying the `sentry` object, then, if no exception was thrown, returning the value specified for the unformatted output function.

4. Modify 27.7.2.3 [istream.unformatted] p1 as indicated:

   > -1- Each unformatted input function begins execution by constructing an object of class `sentry` with the default argument `noskipws` (second) argument true. If the `sentry` object returns true, when converted to a value of type `bool`, the function endeavors to obtain the requested input. Otherwise, if the `sentry` constructor exits by throwing an exception or if the sentry object returns false, when converted to a value of type `bool`, the function returns without attempting to obtain any input. In either case the number of extracted characters is set to `0`; unformatted input functions taking a character array of non-zero size as an argument shall also store a null character (using `charT()`) in the first location of the array. If an exception, other than the ones thrown from `clear()`, if any, is thrown during input then `ios::badbit` is turned on[Footnote 317] in `*this`'s error state. (Exceptions thrown from `basic_ios<>::clear()` are not caught or rethrown.) If `(exceptions() & badbit) != 0` then the exception is rethrown. It also counts the number of characters extracted. If no exception has been thrown it ends by storing the count in a member object and returning the value specified. In any event the `sentry` object is destroyed before leaving the unformatted input function.

### 2351. Does `.seed()` completely reset state of engine?

Section: 26.5.3 [rand.eng] Status: New Submitter: Thomas Plum Opened: 2013-12-02 Last modified: 2014-02-14

View all other issues in [rand.eng].

View all issues with New status.

Discussion:

With regard to Random number engine class templates 26.5.3 [rand.eng], the Standard can be read in two different ways: when the member function

>     .seed(result_type s = default_seed)

is invoked, is all associated state (such as carry) reset to the same state that would have been created by the constructor

>     explicit engine-type(result_type s = default_seed)

or is the exact state unspecified?

Implementations differ.

[2014-02-13, Issaquah]

Walter Brown says that Table 117 makes this very clear, and that the answer is "Yes"

Suggested resolution: NAD

Proposed resolution:

Suggested resolution: NAD

### 2352. Is a default-constructed `std::seed_seq` intended to produce a predictable `.generate()`?

Section: 26.5.7.1 [rand.util.seedseq] Status: New Submitter: Thomas Plum Opened: 2013-12-02 Last modified: 2014-02-11

View all other issues in [rand.util.seedseq].

View all issues with New status.

Discussion:

With respect to class `seed_seq` 26.5.7.1 [rand.util.seedseq], is a default-constructed `std::seed_seq` intended to produce a predictable `.generate()` sequence?

Implementations differ.

Proposed resolution:

### 2353. `std::next` is over-constrained

Section: 24.4.4 [iterator.operations] Status: New Submitter: Eric Niebler Opened: 2013-12-24 Last modified: 2014-02-11

View all other issues in [iterator.operations].

View all issues with New status.

Discussion:

In LWG 1011, `std::next` and `std::prev` were changed from accepting `InputIterator` to accepting `ForwardIterator`. This needlessly excludes perfectly legitimate use cases. Consider the following hypothetical range-based implementation of drop, which creates a view of a range without the first `n` elements:

>     template<typename Distance, typename InputRange>
>     iterator_range<range_iterator_t<InputRange>>
>     drop(Distance n, InputRange& rng)
>     {
>       return make_iterator_range(
>         std::next(std::begin(rng), n),
>         std::end(rng)
>       );
>     }

I believe this to be a legitimate use case that is currently outlawed by the standard without cause. See the discussion beginning at c++std-lib-35313 for an in-depth discussion of the issue, in which Howard Hinnant agreed that it was a defect.

(Some discussion then ensued about whether an overload should be added that only accepts rvalue `InputIterators` to avoid the surprise that issue 1011 sought to address. I make no such attempt, nor do I believe it to be necessary.)

Suggested resolution:

Back out the resolution of 1011.

Proposed resolution:

This wording is relative to N3797.

1. Change 24.3 [iterator.synopsis], header `<iterator>` synopsis, and 24.4.4 [iterator.operations] before p.6 as indicated:

   >     template <class ForwardInputIterator>
   >       ForwardInputIterator next(ForwardInputIterator x,
   >         typename std::iterator_traits<ForwardInputIterator>::difference_type n = 1);

### 2354. Unnecessary copying when inserting into maps with braced-init syntax

Section: 23.4.4.1 [map.overview], 23.4.5.1 [multimap.overview], 23.5.4.1 [unord.map.overview], 23.5.5.1 [unord.multimap.overview] Status: Ready Submitter: Geoffrey Romer Opened: 2014-01-08 Last modified: 2014-02-27

View all issues with Ready status.

Discussion:

The rvalue-reference `insert()` members of `map`, `multimap`, `unordered_map`, and `unordered_multimap` are specified as function templates, where the rvalue-reference parameter type depends on the template parameter. As a consequence, these overloads cannot be invoked via braced-initializer syntax (e.g. `my_map.insert({key, value})`), because the template argument cannot be deduced from a braced-init-list. Such calls instead resolve to the const lvalue reference overload, which forces a non-elidable copy of the argument, despite the fact that the argument is an rvalue, and so should be eligible for moving and copy elision.

This leads to sub-optimal performance for copyable values, and makes this syntax unusable with noncopyable values. This is particularly problematic because sources such as Josuttis's "C++ Standard Library" recommend this syntax as the preferred way to insert into a map in C++11.

I think this can be fixed by adding an equivalent non-template `value_type&&` overload for each affected member template. Simply declaring these members in the class synopses should be sufficient; their semantics are already dictated by the container concepts (c.f. the corresponding lvalue-reference overloads, which have no additional discussion beyond being listed in the synopsis).

[2012-02-13 Issaquah]

AJM: Is this not better solved by `emplace`?

Nico: `emplace` was a mistake, it breaks a uniform pattern designed into the STL. Hence, this fix is important, it should be the preferred way to do this.

JonW: `emplace` is still more efficient, as this form must make a non-elidable copy.

GeoffR: Also, cannot move from a `const` key, must always make a copy.

Poll for adopting the proposed wording:

SF: 1 WF: 4 N: 4 WA: 1 SA: 0

Move to Ready, pending implementation experience.

Proposed resolution:

This wording is relative to N3797.

1. Change 23.4.4.1 [map.overview], class template `map` synopsis, as indicated:

   >     […]
   >     pair<iterator, bool> insert(const value_type& x);
   >     pair<iterator, bool> insert(value_type&& x);
   >     template <class P> pair<iterator, bool> insert(P&& x);
   >     iterator insert(const_iterator position, const value_type& x);
   >     iterator insert(const_iterator position, value_type&& x);
   >     template <class P>
   >       iterator insert(const_iterator position, P&&);
   >     […]

2. Change 23.4.5.1 [multimap.overview], class template `multimap` synopsis, as indicated:

   >     […]
   >     iterator insert(const value_type& x);
   >     iterator insert(value_type&& x);
   >     template <class P> iterator insert(P&& x);
   >     iterator insert(const_iterator position, const value_type& x);
   >     iterator insert(const_iterator position, value_type&& x);
   >     template <class P> iterator insert(const_iterator position, P&& x);
   >     […]

3. Change 23.5.4.1 [unord.map.overview], class template `unordered_map` synopsis, as indicated:

   >     […]
   >     pair<iterator, bool> insert(const value_type& obj);
   >     pair<iterator, bool> insert(value_type&& obj);
   >     template <class P> pair<iterator, bool> insert(P&& obj);
   >     iterator insert(const_iterator hint, const value_type& obj);
   >     iterator insert(const_iterator hint, value_type&& obj);
   >     template <class P> iterator insert(const_iterator hint, P&& obj);
   >     […]

4. Change 23.5.5.1 [unord.multimap.overview], class template `unordered_multimap` synopsis, as indicated:

   >     […]
   >     iterator insert(const value_type& obj);
   >     iterator insert(value_type&& obj);
   >     template <class P> iterator insert(P&& obj);
   >     iterator insert(const_iterator hint, const value_type& obj);
   >     iterator insert(const_iterator hint, value_type&& obj);
   >     template <class P> iterator insert(const_iterator hint, P&& obj);
   >     […]

### 2358. Apparently-bogus definition of `is_empty` type trait

Section: 20.10.4.3 [meta.unary.prop] Status: New Submitter: Richard Smith Opened: 2014-02-01 Last modified: 2014-02-11

View other active issues in [meta.unary.prop].

View all other issues in [meta.unary.prop].

View all issues with New status.

Discussion:

The 'Condition' for `std::is_empty` is listed as:

> "`T` is a class type, but not a union type, with no non-static data members other than bit-fields of length 0, no virtual member functions, no virtual base classes, and no base class `B` for which `is_empty<B>::value` is false."

This is incorrect: there is no such thing as a non-static data member that is a bit-field of length 0, since bit-fields of length 0 must be unnamed, and unnamed bit-fields are not members (see 9.6 [class.bit] p2).

It also means that classes such as:

>     struct S {
>      int : 3;
>     };

are empty (because they have no non-static data members). There's implementation divergence on the value of `is_empty<S>::value`.

I'm not sure what the purpose of `is_empty` is (or how it could be useful), but if it's desirable for the above type to not be treated as empty, something like this could work:

> "`T` is a class type, but not a union type, with no non-static data members other than, no unnamed bit-fields of non-zero length 0, no virtual member functions, no virtual base classes, and no base class `B` for which `is_empty<B>::value` is false."

and if the above type should be treated as empty, then this might be appropriate:

> "`T` is a class type, but not a union type, with no (named) non-static data members other than bit-fields of length 0, no virtual member functions, no virtual base classes, and no base class `B` for which `is_empty<B>::value` is false."

Proposed resolution:

### 2361. Apply 2299 resolution throughout library

Section: 20.8.1.2 [unique.ptr.single], 20.7.3.1 [pointer.traits.types], 20.7.7.1 [allocator.uses.trait], 20.7.8.1 [allocator.traits.types], 23.2.3 [sequence.reqmts] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2014-02-14 Last modified: 2014-05-23

View other active issues in [unique.ptr.single].

View all other issues in [unique.ptr.single].

View all issues with Tentatively Ready status.

Discussion:

LWG 2299 addressed a N.B. comment pointing out that recently added wording about a type existing was not clear what happens if the type exists but is inaccessible. There are 16 pre-existing uses of the same language in the library that should use the same wording used to resolve 2299.

The relevant paragraphs are:

20.8.1.2 [unique.ptr.single]

20.7.3.1 [pointer.traits.types]

20.7.7.1 [allocator.uses.trait]

20.7.8.1 [allocator.traits.types]

23.2.3 [sequence.reqmts]

[2014-05-16, Daniel provides wording]

[2014-05-18 Library reflector vote]

The issue has been identified as Tentatively Ready based on six votes in favour.

Proposed resolution:

This wording is relative to N3936.

1. Change 20.7.3.1 [pointer.traits.types] as indicated:

   >     typedef see below element_type;

   > > -1- Type: `Ptr::element_type` if such a type exists the qualified-id `Ptr::element_type` is valid and denotes a type (14.8.2 [temp.deduct]); otherwise, `T` if `Ptr` is a class template instantiation of the form `SomePointer<T, Args>`, where `Args` is zero or more type arguments; otherwise, the specialization is ill-formed.

   >     typedef see below difference_type;

   > > -2- Type: `Ptr::difference_type` if such a type exists the qualified-id `Ptr::difference_type` is valid and denotes a type (14.8.2 [temp.deduct]); otherwise, `std::ptrdiff_t`.

   >     template <class U> using rebind = see below;

   > > -3- Alias template: `Ptr::rebind<U>` if such a type exists the qualified-id `Ptr::rebind<U>` is valid and denotes a type (14.8.2 [temp.deduct]); otherwise, `SomePointer<U, Args>` if `Ptr` is a class template instantiation of the form `SomePointer<T, Args>`, where `Args` is zero or more type arguments; otherwise, the instantiation of `rebind` is ill-formed.

2. Change 20.7.7.1 [allocator.uses.trait] p1 as indicated:

   >     template <class T, class Alloc> struct uses_allocator;

   > > -1- Remarks: automatically detects whether `T` has a nested `allocator_type` that is convertible from `Alloc`. Meets the `BinaryTypeTrait` requirements (20.10.1). The implementation shall provide a definition that is derived from `true_type` if a type the qualified-id `T::allocator_type` exists is valid and denotes a type (14.8.2 [temp.deduct]) and `is_convertible<Alloc, T::allocator_type>::value != false`, otherwise it shall be derived from `false_type`. […]

3. Change 20.7.8.1 [allocator.traits.types] as indicated:

   >     typedef see below pointer;

   > > -1- Type: `Alloc::pointer` if such a type exists the qualified-id `Alloc::pointer` is valid and denotes a type (14.8.2 [temp.deduct]); otherwise, `value_type*`.

   >     typedef see below const_pointer;

   > > -2- Type: `Alloc::const_pointer` if such a type exists the qualified-id `Alloc::const_pointer` is valid and denotes a type (14.8.2 [temp.deduct]); otherwise, `pointer_traits<pointer>::rebind<const value_type>`.

   >     typedef see below void_pointer;

   > > -3- Type: `Alloc::void_pointer` if such a type exists the qualified-id `Alloc::void_pointer` is valid and denotes a type (14.8.2 [temp.deduct]); otherwise, `pointer_traits<pointer>::rebind<void>`.

   >     typedef see below const_void_pointer;

   > > -4- Type: `Alloc::const_void_pointer` if such a type exists the qualified-id `Alloc::const_void_pointer` is valid and denotes a type (14.8.2 [temp.deduct]); otherwise, `pointer_traits<pointer>::rebind<const void>`.

   >     typedef see below difference_type;

   > > -5- Type: `Alloc::difference_type` if such a type exists the qualified-id `Alloc::difference_type` is valid and denotes a type (14.8.2 [temp.deduct]); otherwise, `pointer_traits<pointer>::difference_type`.

   >     typedef see below size_type;

   > > -6- Type: `Alloc::size_type` if such a type exists the qualified-id `Alloc::size_type` is valid and denotes a type (14.8.2 [temp.deduct]); otherwise, `make_unsigned_t<difference_type>`.

   >     typedef see below propagate_on_container_copy_assignment;

   > > -7- Type: `Alloc::propagate_on_container_copy_assignment` if such a type exists the qualified-id `Alloc::propagate_on_container_copy_assignment` is valid and denotes a type (14.8.2 [temp.deduct]); otherwise, `false_type`.

   >     typedef see below propagate_on_container_move_assignment;

   > > -8- Type: `Alloc::propagate_on_container_move_assignment` if such a type exists the qualified-id `Alloc::propagate_on_container_move_assignment` is valid and denotes a type (14.8.2 [temp.deduct]); otherwise, `false_type`.

   >     typedef see below propagate_on_container_swap;

   > > -9- Type: `Alloc::propagate_on_container_swap` if such a type exists the qualified-id `Alloc::propagate_on_container_swap` is valid and denotes a type (14.8.2 [temp.deduct]); otherwise, `false_type`.

   >     template <class T> using rebind_alloc = see below;

   > > -10- Alias template: `Alloc::rebind<T>::other` if such a type exists the qualified-id `Alloc::rebind<T>::other` is valid and denotes a type (14.8.2 [temp.deduct]); otherwise, `Alloc<T, Args>` if `Alloc` is a class template instantiation of the form `Alloc<U, Args>`, where `Args` is zero or more type arguments; otherwise, the instantiation of `rebind_alloc` is ill-formed.

4. Change 20.8.1.2 [unique.ptr.single] p3 as indicated:

   > -3- If the type qualified-id `remove_reference_t<D>::pointer` exists is valid and denotes a type (14.8.2 [temp.deduct]), then `unique_ptr<T, D>::pointer` shall be a synonym for `remove_reference_t<D>::pointer`. […]

5. Change 23.2.3 [sequence.reqmts] p3 as indicated:

   > -3- In Tables 100 and 101, `X` denotes a sequence container class, `a` denotes a value of `X` containing elements of type `T`, `A` denotes `X::allocator_type` if it exists the qualified-id `X::allocator_type` is valid and denotes a type (14.8.2 [temp.deduct]) and `std::allocator<T>` if it doesn't, […]

### 2362. unique, associative `emplace()` should not move/copy the `mapped_type` constructor arguments when no insertion happens

Section: 23.2.4 [associative.reqmts], 23.2.5 [unord.req] Status: New Submitter: Jeffrey Yasskin Opened: 2014-02-15 Last modified: 2014-06-17

View other active issues in [associative.reqmts].

View all other issues in [associative.reqmts].

View all issues with New status.

Discussion:

`a_uniq.emplace(args)` is specified as:

> Effects: Inserts a value_type object `t` constructed with
> `std::forward<Args>(args)...` if and only if there is no element in the
> container with key equivalent to the key of `t`. The `bool` component of
> the returned pair is true if and only if the insertion takes place,
> and the iterator component of the pair points to the element with key
> equivalent to the key of `t`.

However, we occasionally find code of the form:

>     std::unique_ptr<Foo> p(new Foo);
>     auto res = m.emplace("foo", std::move(p));

where we'd like to avoid destroying the `Foo` if the insertion doesn't take place (if the container already had an element with the specified key).

N3873 includes a partial solution to this in the form of a new `emplace_stable` member function, but LEWG's discussion strongly agreed that we'd rather have `emplace()` Just Work:

Should `map::emplace()` be guaranteed not to move/copy its arguments if the insertion doesn't happen?

SF: 8 F: 3 N: 0 A: 0 SA: 0

This poll was marred by the fact that we didn't notice or call out that `emplace()` must construct the key before doing the lookup, and it must not then move the key after it determines whether an insert is going to happen, and the `mapped_type` instance must live next to the key.

The very similar issue 2006 was previously marked NAD, with N3178 as discussion. However, given LEWG's interest in the alternate behavior, we should reopen the question in this issue.

We will need a paper that describes how to implement this before we can make more progress.

Proposed resolution:

### 2363. Defect in 30.4.1.4.1 [thread.sharedtimedmutex.class]

Section: 30.4.1.4.1 [thread.sharedtimedmutex.class] Status: New Submitter: Richard Smith Opened: 2014-02-16 Last modified: 2014-06-17

View all issues with New status.

Discussion:

30.4.1.4.1 [thread.sharedtimedmutex.class] paragraph 2:

> The class `shared_timed_mutex` shall satisfy all of the `SharedTimedMutex` requirements (30.4.1.4). It shall be a standard layout class (Clause 9).

There's no `SharedTimedMutex` requirements; this name doesn't appear anywhere else in the standard. (Prior to N3891, this was `SharedMutex`, which was equally undefined.)

I assume this concept should be defined somewhere?

Also, n3891 changes 30.4.1.4 [thread.sharedtimedmutex.requirements] from defining "shared mutex type" to defining "shared timed mutex type", but its paragraph 2 still talks about "shared mutex type". Is that OK? I think you could argue that it's clear enough what it means, but presumably it should use the term that paragraph 1 defined.

30.4.2.3 [thread.lock.shared] paragraph 1 talks about the "shared mutex requirements", which again is a term that isn't defined, and presumably means "the requirements on a shared timed mutex type" or similar (maybe if `SharedMutex` or `SharedTimedMutex` were defined it could be reused here).

[2014-05-22, Daniel comments]

As for `SharedTimedMutex`, there exists a similar problem in regard to `TimedMutex` referred to in 30.4.1.3.1 [thread.timedmutex.class] p2 and in 30.4.1.3.2 [thread.timedmutex.recursive] p2, but nowhere defined.

Another problem is, that according to 30.4.1.2.1 [thread.mutex.class] p3, "The class `mutex` shall satisfy all the `Mutex` requirements (30.4.1 [thread.mutex.requirements]).", but there are no concrete `Mutex` requirements, 30.4.1 [thread.mutex.requirements] — titled as "Mutex requirements" — describes mutex types, timed mutex types, and shared timed mutex types.

[2014-06-08, Daniel comments and provides wording]

The presented wording adds to the existing mutex types, timed mutex types, and shared timed mutex types terms a new set of corresponding `MutexType`, `TimedMutexType`, and `SharedTimedMutexType` requirements.

The reason for the change of requirement names is two-fold: First, the new name better matches the intention to have a concrete name for the requirements imposed on the corresponding mutex types (This kind of requirement deviate from the more general `Lockable` requirements, which are not restricted to a explicitly enumerated set of library types). Second, using `**MutexType` over `**Mutex` provides the additional advantage that it reduces the chances of confusing named requirements from template parameters named `Mutex` (such as for `unique_lock` or `shared_lock`).

Nonetheless the here presented wording has one unfortunate side-effect: Once applied it would have the effect that types used to instantiate `std::shared_lock` cannot be user-defined shared mutex types due to 30.4.2.3 [thread.lock.shared]. The reason is based on the currently lack of an existing `SharedLockable` requirement set, which would complete the existing `BasicLockable` and `Lockable` requirements (which are "real" requirements). This restriction is not actually a problem introduced by the provided resolution but instead one that existed before but becomes more obvious now.

Proposed resolution:

This wording is relative to N3936.

1. Change 30.4.1.2 [thread.mutex.requirements.mutex] as indicated:

   > -1- The mutex types are the standard library types `std::mutex`, `std::recursive_mutex`, `std::timed_mutex`, `std::recursive_timed_mutex`, and `std::shared_timed_mutex`. They shall meet the `MutexType` requirements set out in this section. In this description, `m` denotes an object of a mutex type.

2. Change 30.4.1.2.1 [thread.mutex.class] as indicated:

   > -3- The class `mutex` shall satisfy all the `MutexType` requirements (30.4.1.2 [thread.mutex.requirements.mutex]30.4.1 [thread.mutex.requirements]). It shall be a standard-layout class (Clause 9).

3. Change 30.4.1.2.2 [thread.mutex.recursive] as indicated:

   > -2- The class `recursive_mutex` shall satisfy all the Mutex `MutexType` requirements (30.4.1.2 [thread.mutex.requirements.mutex]30.4.1 [thread.mutex.requirements]). It shall be a standard-layout class (Clause 9).

4. Change 30.4.1.3 [thread.timedmutex.requirements] as indicated:

   > -1- The timed mutex types are the standard library types `std::timed_mutex`, `std::recursive_timed_mutex`, and `std::shared_timed_mutex`. They shall meet the `TimedMutexType` requirements set out below. In this description, `m` denotes an object of a mutex type, `rel_time` denotes an object of an instantiation of `duration` (20.12.5), and `abs_time` denotes an object of an instantiation of `time_point` (20.12.6).

5. Change 30.4.1.3.1 [thread.timedmutex.class] as indicated:

   > -2- The class `timed_mutex` shall satisfy all of the `TimedMutexType` requirements (30.4.1.3 [thread.timedmutex.requirements]). It shall be a standard-layout class (Clause 9).

6. Change 30.4.1.3.2 [thread.timedmutex.recursive] as indicated:

   > -2- The class `recursive_timed_mutex` shall satisfy all of the `TimedMutexType` requirements (30.4.1.3 [thread.timedmutex.requirements]). It shall be a standard-layout class (Clause 9).

7. Change 30.4.1.4 [thread.sharedtimedmutex.requirements] as indicated: [Drafting note: The reference to the timed mutex types requirements has been moved after introducing the new requirement set to ensure that `SharedTimedMutexType` refine `TimedMutexType`.]

   > -1- The standard library type `std::shared_timed_mutex` is a shared timed mutex type. Shared timed mutex types shall meet the `SharedTimedMutexType` requirements of timed mutex types (30.4.1.3 [thread.timedmutex.requirements]), and additionally shall meet the requirements set out below. In this description, `m` denotes an object of a mutex type, `rel_type` denotes an object of an instantiation of `duration` (20.12.5), and `abs_time` denotes an object of an instantiation of `time_point` (20.12.6).

   > -?- The shared timed mutex types shall meet the `TimedMutexType` requirements (30.4.1.3 [thread.timedmutex.requirements]).

8. Change 30.4.1.4.1 [thread.sharedtimedmutex.class] as indicated:

   > -2- The class `shared_timed_mutex` shall satisfy all of the `SharedTimedMutexType` requirements (30.4.1.4 [thread.sharedtimedmutex.requirements]). It shall be a standard-layout class (Clause 9).

9. Change 30.4.2.3 [thread.lock.shared] as indicated: [Drafting note: Once N3995 has been applied, the following reference should be changed to the new `SharedMutexType` requirements ([thread.sharedmutex.requirements]) or even better to some new `SharedLockable` requirements (to be defined) — end drafting note]

   > -1- […] The supplied `Mutex` type shall meet the shared mutex `SharedTimedMutexType` requirements (30.4.1.4 [thread.sharedtimedmutex.requirements]).

   > -2- [Note: `shared_lock<Mutex>` meets the `TimedLockable` requirements (30.2.5.4). — end note]

### 2364. `deque` and `vector` `pop_back` don't specify iterator invalidation requirements

Section: 23.3.3.4 [deque.modifiers], 23.3.6.5 [vector.modifiers] Status: Review Submitter: Deskin Miller Opened: 2014-02-17 Last modified: 2014-07-01

View all other issues in [deque.modifiers].

View all issues with Review status.

Discussion:

I think it's obvious that `vector::pop_back` invalidates the path-the-end iterator, but I cannot find language that says so to my satisfaction in the Standard. N3797 23.2.3 [sequence.reqmts] Table 101 lists `a.pop_back()` semantics as "Destroys the last element", but nowhere do I see this required to invalidate the end iterator (or iterators previously referring to the last element). [container.reqmts.general]/11 states "Unless otherwise specified (either explicitly or by defining a function in terms of other functions), invoking a container member function or passing a container as an argument to a library function shall not invalidate iterators to, or change the values of, objects within that container." 23.3.6.5 [vector.modifiers]/3 says that each flavor of `vector::erase` "Invalidates iterators and references at or after the point of the erase", but `pop_back` isn't discussed, and it wasn't specified in terms of `erase`.

Similarly for `std::deque`, 23.2.3 [sequence.reqmts] Table 101 and [container.reqmts.general]/11 both apply. Yet 23.3.3.4 [deque.modifiers] likewise doesn't discuss `pop_back` nor `pop_front`. Furthermore paragraph 4 fails to specify the iterator-invalidation guarantees when erasing the first element but not the last.

Both `std::vector` and `std::deque` are in contrast to `std::list`, which says in 23.3.5.4 [list.modifiers]/3 regarding `pop_back` (as well as all forms of `erase`, `pop_front`, and `clear`) "Effects: Invalidates only the iterators and references to the erased elements."

[2014-06-16 Jonathan comments and improves wording]

I believe this reflects our preferred form discussed earlier, specifically putting the signatures with the `erase` signatures, so that the full specification of `erase()` applies to the `pop_xxx()` functions. This covers the case for `deque` where `pop_front()` erases the only element (which is both the first and last element).

Open question: the "erase" wording talks about "An erase operation" — are `pop_front` and `pop_back` clearly covered by "erase operations"? I believe so, as 23.3.3.1 [deque.overview]/1 and other places talk about "insert and erase operations" which covers `push`/`pop` functions too. I've added a note which could be used to clarify that if desired. Previous resolution [SUPERSEDED]:

> This wording is relative to N3936.

> 1. Change 23.3.3.4 [deque.modifiers] as indicated:

>    >     iterator erase(const_iterator position);
>    >     iterator erase(const_iterator first, const_iterator last);

>    > > -4- Effects: An erase operation that erases the last element of a deque invalidates only the past-the-end iterator and all iterators and references to the erased elements. An erase operation that erases the first element of a deque but not the last element invalidates only iterators and references to the erased elements. An erase operation that erases neither the first element nor the last element of a deque invalidates the past-the-end iterator and all iterators and references to all the elements of the deque.

>    > > -5- […]

>    > > -6- […]

>    >     void pop_front();
>    >     void pop_back();

>    > > -?- Effects: `pop_front` invalidates iterators and references to the first element of the `deque`. `pop_back` invalidates the past-the-end iterator, and all iterators and references to the last element of the `deque`.

> 2. Change 23.3.6.5 [vector.modifiers] as indicated:

>    > > -5- […]

>    >     void pop_back();

>    > > -?- Effects: Invalidates the past-the-end iterator, and iterators and references to the last element of the vector.

[2014-06-21 Rapperswil]

Tony van Eerd: Would be good to define "an erase operation is ..." somewhere.

AM: The containers clause is known to be suboptimal in many ways.

Looks good

Proposed resolution:

This wording is relative to N3936.

1. Change 23.3.3.4 [deque.modifiers] as indicated:

   >     iterator erase(const_iterator position);
   >     iterator erase(const_iterator first, const_iterator last);
   >     void pop_front();
   >     void pop_back();

   > > -4- Effects: An erase operation that erases the last element of a deque invalidates only the past-the-end iterator and all iterators and references to the erased elements. An erase operation that erases the first element of a deque but not the last element invalidates only iterators and references to the erased elements. An erase operation that erases neither the first element nor the last element of a deque invalidates the past-the-end iterator and all iterators and references to all the elements of the deque. [Note: `pop_front` and `pop_back` are erase operations — end note]

2. Change 23.3.6.5 [vector.modifiers] as indicated:

   >     iterator erase(const_iterator position);
   >     iterator erase(const_iterator first, const_iterator last);
   >     void pop_back();

   > > -3- Effects: Invalidates iterators and references at or after the point of the erase.

### 2365. Missing `noexcept` in `shared_ptr::shared_ptr(nullptr_t)`

Section: 20.8.2.2 [util.smartptr.shared] Status: Tentatively Ready Submitter: Cassio Neri Opened: 2014-02-13 Last modified: 2014-05-02

View other active issues in [util.smartptr.shared].

View all other issues in [util.smartptr.shared].

View all issues with Tentatively Ready status.

Discussion:

The declaration and definition of `shared_ptr::shared_ptr(nullptr_t)`, given in 20.8.2.2 [util.smartptr.shared], is

>     constexpr shared_ptr(nullptr_t) : shared_ptr() { }

The intention seems clear: this constructor should have the same semantics of the default constructor. However, contrarily to the default constructor, this one is not `noexcept`. In contrast, `unique_ptr::unique_ptr(nullptr_t)` is `noexcept`, as per 20.8.1.2 [unique.ptr.single]:

>     constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }

Both libstdc++ and libc++ have added `noexcept` to `shared_ptr::shared_ptr(nullptr_t)`. Microsoft's STL has not.

[2014-03-26 Library reflector vote]

The issue has been identified as Tentatively Ready based on six votes in favour.

Proposed resolution:

This wording is relative to N3936.

1. Change class template `shared_ptr` synopsis, 20.8.2.2 [util.smartptr.shared], as indicated:

   >     constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }

### 2366. `istreambuf_iterator` end-of-stream equality

Section: 24.6.3 [istreambuf.iterator] Status: New Submitter: Hyman Rosen Opened: 2014-02-19 Last modified: 2014-06-17

View all other issues in [istreambuf.iterator].

View all issues with New status.

Discussion:

Given the following code,

>     #include <sstream>

>     std::stringbuf buf;
>     std::istreambuf_iterator<char> begin(&buf);
>     std::istreambuf_iterator<char> end;

it is not clear from the wording of the Standard whether `begin.equal(end)` must be true. In at least one implementation it is not (CC: Sun C++ 5.10 SunOS_sparc Patch 128228-25 2013/02/20) and in at least one implementation it is (gcc version 4.3.2 x86_64-unknown-linux-gnu).

24.6.3 [istreambuf.iterator] says that `end` is an end-of-stream iterator since it was default constructed. It also says that an iterator becomes equal to an end-of-stream iterator when end of stream is reached by `sgetc()` having returned `eof()`. 24.6.3.5 [istreambuf.iterator::equal] says that `equal()` returns true iff both iterators are end of stream or not end of stream. But there seems to be no requirement that `equal` check for end-of-stream by calling `sgetc()`.

Jiahan Zi at BloombergLP discovered this issue through his code failing to work correctly. Dietmar Kühl has opined in a private communication that the iterators should compare equal.

Proposed resolution:

### 2367. `pair` and `tuple` are not correctly implemented for `is_constructible` with no args

Section: 20.10.4.3 [meta.unary.prop] Status: New Submitter: Howard Hinnant Opened: 2014-02-19 Last modified: 2014-06-17

View other active issues in [meta.unary.prop].

View all other issues in [meta.unary.prop].

View all issues with New status.

Discussion:

Consider:

>     struct X
>     {
>       X() = delete;
>     };

>     int main()
>     {
>       typedef std::pair<int, X> P;
>       static_assert(!std::is_constructible<P>::value, "");
>       static_assert(!std::is_default_constructible<P>::value, "");
>       typedef std::tuple<int, X> T;
>       static_assert(!std::is_constructible<T>::value, "");
>       static_assert(!std::is_default_constructible<T>::value, "");
>     }

For me these `static_asserts` fail. And worse than that, even asking the question fails (as opposed to gets the wrong answer):

>     assert(!std::is_constructible<P>::value);

In file included from test.cpp:2:

>     error:
>           call to deleted constructor of 'X'
>        pair() : first(), second() {}
>                          ^
>     note: function has been explicitly marked deleted here
>         X() = delete;
>         ^
>     1 error generated.

This can be solved by specializing `is_constructible` on `pair` and `tuple` for zero Args:

>     template <class T, class U>
>     struct is_constructible<pair<T, U>>
>       : integral_constant<bool, is_default_constructible<T>::value &&
>                                 is_default_constructible<U>::value>
>     {};

>     template <class ...T>
>     struct is_constructible<tuple<T...>>
>       : integral_constant<bool,
>                           __all<is_default_constructible<T>::value...>::value>
>     {};

Now everything just works.

[2014-05-14, Daniel comments]

The proposed resolution is incomplete, because it wouldn't work for cv-qualified objects of `pair` or for references of them during reference-initialization.

I would like to point out that the approach suggested in N3739 can be easily extended to solve the problem without need to muddle with specializing `is_constructible`:

>     template<class U1 = T1, class U2 = T2,
>       typename enable_if<
>         is_default_constructible<U1>::value && is_default_constructible<U2>::value
>       , bool>::type = false
>     >
>     constexpr pair();

The new wording proposal represents an alternative wording change that I would strongly prefer.

Previous resolution from Howard [SUPERSEDED]:

> This wording is relative to N3936.

> 1. Add to 20.3.3 [pairs.spec]:

>    >     template <class T, class U>
>    >     struct is_constructible<pair<T, U>>
>    >       : integral_constant<bool, is_default_constructible<T>::value &&
>    >                                 is_default_constructible<U>::value>
>    >     {};

> 2. Add to 20.4.2.9 [tuple.special]:

>    >     template <class ...T>
>    >     struct is_constructible<tuple<T...>>
>    >       : integral_constant<bool, see below>
>    >     {};

>    > > -?- The second argument to `integral_constant` shall be true if for each `T`, `is_default_constructible<T>::value` is true.

Proposed resolution:

This wording is relative to N3936.

1. Change 20.3.2 [pairs.pair] around p3 as indicated:

   >     constexpr pair();

   > > -3- Requires: `is_default_constructible<first_type>::value` is true and `is_default_constructible<second_type>::value` is true.

   > > -4- Effects: Value-initializes first and second.

   > > -?- Remarks: This constructor shall not participate in overload resolution unless `is_default_constructible<first_type>::value` is true and `is_default_constructible<second_type>::value` is true. [Note: This behaviour can be implemented by a constructor template with default template arguments — end note].

2. Change 20.4.2.1 [tuple.cnstr] around p4 as indicated:

   >     constexpr tuple();

   > > -4- Requires: `is_default_constructible<Ti>::value` is true for all i.

   > > -5- Effects: Value initializes each element.

   > > -?- Remarks: This constructor shall not participate in overload resolution unless `is_default_constructible<Ti>::value` is true for all i. [Note: This behaviour can be implemented by a constructor template with default template arguments — end note].

### 2368. Replacing global `operator new`

Section: 18.6.1 [new.delete] Status: New Submitter: Stephen Clamage Opened: 2014-02-20 Last modified: 2014-06-17

View all other issues in [new.delete].

View all issues with New status.

Discussion:

Section 18.6.1 [new.delete] and subsections shows:

>     void* operator new(std::size_t size);
>     void* operator new[](std::size_t size);

That is, without exception-specifications. (Recall that C++03 specified these functions with `throw(std::bad_alloc)`.)

Section 17.6.5.12 [res.on.exception.handling] the end of paragraph 4 says:

> Any other functions defined in the C++ standard library that do not have an exception-specification may throw implementation-defined exceptions unless otherwise specified. An implementation may strengthen this implicit exception-specification by adding an explicit one.

For example, an implementation could provide C++03-compatible declarations of `operator new`.

Programmers are allowed to replace these `operator new` functions. But how can you write the definition of these functions when the exception specification can vary among implementations? For example, the declarations

>     void* operator new(std::size_t size) throw(std::bad_alloc);
>     void* operator new(std::size_t size);

are not compatible.

From what I have been able to determine, gcc has a hack for the special case of `operator new` to ignore the differences in (at least) the two cases I show above. But can users expect all compilers to quietly ignore the incompatibility?

The blanket permission to add any explicit exception specification could cause a problem for any user-overridable function. Different implementations could provide incompatible specifications, making portable code impossible to write.

Proposed resolution:

### 2369. `constexpr max(initializer_list)` vs `max_element`

Section: 25.4.7 [alg.min.max] Status: New Submitter: Marc Glisse Opened: 2014-02-21 Last modified: 2014-06-17

View other active issues in [alg.min.max].

View all other issues in [alg.min.max].

View all issues with New status.

Discussion:

As part of the resolution for LWG issue 2350, `max(initializer_list)` was marked as `constexpr`. Looking at two implementations of this function (libstdc++ and libc++), both implement it in terms of `max_element`, which is not marked as `constexpr`. This is inconsistent and forces some small amount of code duplication in the implementation. Unless we remove `constexpr` from this overload of `max`, I believe we should add `constexpr` to `max_element`.

Proposed resolution:

This wording is relative to N3936.

1. In 25.1 [algorithms.general], header `<algorithm>` synopsis, and 25.4.7 [alg.min.max], change as indicated (add `constexpr` to every signature from the first `min_element` to the second `minmax_element`)::

   >     template<class ForwardIterator>
   >     constexpr ForwardIterator min_element(ForwardIterator first, ForwardIterator last);
   >     template<class ForwardIterator, class Compare>
   >     constexpr ForwardIterator min_element(ForwardIterator first, ForwardIterator last,
   >                                           Compare comp);
   >     […]
   >     template<class ForwardIterator>
   >     constexpr ForwardIterator max_element(ForwardIterator first, ForwardIterator last);
   >     template<class ForwardIterator, class Compare>
   >     constexpr ForwardIterator max_element(ForwardIterator first, ForwardIterator last,
   >                                           Compare comp);
   >     […]
   >     template<class ForwardIterator>
   >     constexpr pair<ForwardIterator, ForwardIterator>
   >     minmax_element(ForwardIterator first, ForwardIterator last);
   >     template<class ForwardIterator, class Compare>
   >     constexpr pair<ForwardIterator, ForwardIterator>
   >     minmax_element(ForwardIterator first, ForwardIterator last, Compare comp);

### 2370. Operations involving type-erased allocators should not be `noexcept` in `std::function`

Section: 20.9.11.2 [func.wrap.func] Status: New Submitter: Pablo Halpern Opened: 2014-02-27 Last modified: 2014-06-17

View other active issues in [func.wrap.func].

View all other issues in [func.wrap.func].

View all issues with New status.

Discussion:

The following constructors in 20.9.11.2 [func.wrap.func] are declared `noexcept`, even though it is not possible for an implementation to guarantee that they will not throw:

>     template <class A> function(allocator_arg_t, const A&) noexcept;
>     template <class A> function(allocator_arg_t, const A&, nullptr_t) noexcept;

In addition, the following functions are guaranteed not to throw if the target is a function pointer or a `reference_wrapper`:

>     template <class A> function(allocator_arg_t, const A& a, const function& f);
>     template <class F, class A> function(allocator_arg_t, const A& a, F f);

In all of the above cases, the function object might need to allocate memory (an operation that can throw) in order to hold a copy of the type-erased allocator itself. The first two constructors produce an empty function object, but the allocator is still needed in case the object is later assigned to. In this case, we note that the propagation of allocators on assignment is underspecified for `std::function`. There are three possibilities:

1. The allocator is never copied on copy-assignment, moved on move-assignment, or swapped on swap.

2. The allocator is always copied on copy-assignment, moved on move-assignment, and swapped on swap.

3. Whether or not the allocator is copied, moved, or swapped is determined at run-time based on the `propagate_on_container_copy_assignment` and `propagate_on_container_move_assignment` traits of the allocators at construction of the source function, the target function, or both.

Although the third option seems to be the most consistent with existing wording in the containers section of the standard, it is problematic in a number of respects. To begin with, the propagation behavior is determined at run time based on a pair of type-erased allocators, instead of at compile time. Such run-time logic is not consistent with the rest of the standard and is hard to reason about. Additionally, there are two allocator types involved, rather than one. Any set of rules that attempts to rationally interpret the propagation traits of both allocators is likely to be arcane at best, and subtly wrong for some set of codes at worst.

The second option is a non-starter. Historically, and in the vast majority of existing code, an allocator does not change after an object is constructed. The second option, if adopted, would undermine the programmer's ability to construct, e.g., an array of function objects, all using the same allocator.

The first option is (in Pablo's opinion) the simplest and best. It is consistent with historical use of allocators, is easy to understand, and requires minimal wording. It is also consistent with the wording in N3916, which formalizes type-erased allocators.

For cross-referencing purposes: The resolution of this issue should be harmonized with any resolution to LWG 2062, which questions the `noexcept` specification on the following member functions of std::function:

>     template <class F> function& operator=(reference_wrapper<F>) noexcept;
>     void swap(function&) noexcept;

Proposed resolution:

This wording is relative to N3936.

1. Change 20.9.11.2 [func.wrap.func], class template `function` synopsis, as indicated:

   >     template <class A> function(allocator_arg_t, const A&) noexcept;
   >     template <class A> function(allocator_arg_t, const A&, nullptr_t) noexcept;

2. Change 20.9.11.2.1 [func.wrap.func.con] as indicated:

   > -1- When any function constructor that takes a first argument of type `allocator_arg_t` is invoked, the second argument shall have a type that conforms to the requirements for `Allocator` (Table 17.6.3.5). A copy of the allocator argument is used to allocate memory, if necessary, for the internal data structures of the constructed function object. For the remaining constructors, an instance of `allocator<T>`, for some suitable type `T`, is used to allocate memory, if necessary, for the internal data structures of the constructed function object.

   >     function() noexcept;
   >     template <class A> function(allocator_arg_t, const A&) noexcept;

   > > -2- Postconditions: `!*this`.

   >     function(nullptr_t) noexcept;
   >     template <class A> function(allocator_arg_t, const A&, nullptr_t) noexcept;

   > > -3- Postconditions: `!*this`.

   >     function(const function& f);
   >     template <class A> function(allocator_arg_t, const A& a, const function& f);

   > > -4- Postconditions: `!*this` if `!f`; otherwise, `*this` targets a copy of `f.target()`.

   > > -5- Throws: shall not throw exceptions if `f`'s target is a callable object passed via `reference_wrapper` or a function pointer. Otherwise, may throw `bad_alloc` or any exception thrown by the copy constructor of the stored callable object. [Note: Implementations are encouraged to avoid the use of dynamically allocated memory for small callable objects, for example, where `f`'s target is an object holding only a pointer or reference to an object and a member function pointer. — end note]

   >     template <class A> function(allocator_arg_t, const A& a, const function& f);

   > > -?- Postconditions: `!*this` if `!f`; otherwise, `*this` targets a copy of `f.target()`.

   >     function(function&& f);
   >     template <class A> function(allocator_arg_t, const A& a, function&& f);

   > > -6- Effects: If `!f`, `*this` has no target; otherwise, move-constructs the target of `f` into the target of `*this`, leaving `f` in a valid state with an unspecified value. If an allocator is not specified, the constructed function will use the same allocator as `f`.

   >     template<class F> function(F f);
   >     template <class F, class A> function(allocator_arg_t, const A& a, F f);

   > > -7- Requires: `F` shall be `CopyConstructible`.

   > > -8- Remarks: These constructors shall not participate in overload resolution unless `f` is Callable (20.9.11.2) for argument types `ArgTypes...` and return type `R`.

   > > -9- Postconditions: `!*this` if any of the following hold:

   > > - `f` is a null function pointer value.

   > > - `f` is a null member pointer value.

   > > - `F` is an instance of the function class template, and `!f`

   > > -10- Otherwise, `*this` targets a copy of `f` initialized with `std::move(f)`. [Note: Implementations are encouraged to avoid the use of dynamically allocated memory for small callable objects, for example, where `f`'s target is an object holding only a pointer or reference to an object and a member function pointer. — end note]

   > > -11- Throws: shall not throw exceptions when an allocator is not specified and `f` is a function pointer or a `reference_wrapper<T>` for some `T`. Otherwise, may throw `bad_alloc` or any exception thrown by `F`'s copy or move constructor or by `A`'s allocate function.

### 2372. Assignment from int to `std::string`

Section: 21.4 [basic.string] Status: New Submitter: Andrzej Krzemieński Opened: 2014-03-13 Last modified: 2014-06-17

View other active issues in [basic.string].

View all other issues in [basic.string].

View all issues with New status.

Discussion:

The following code works in C++:

>     int i = 300;
>     std::string threeHundred;
>     threeHundred = i;

"Works" == "Compiles and doesn't have an undefined behavior". But it may not be obvious and in fact misleading what it does. This assignment converts an `int` to `char` and then uses `string`'s assignment from `char`. While the assignment from `char` can be considered a feature, being able to assign from an int looks like a safety gap. Someone may believe C++ works like "dynamically typed" languages and expect a lexical conversion to take place.

Ideally the assignment from `char` could be deprecated and later removed, but as a less intrusive alternative one could consider adding a SFINAEd deleted function template:

>     template <typename IntT> // enable if is_integral<IntT>::value
>     basic_string& operator=(IntT) = delete;

Proposed resolution:

This wording is relative to N3936.

1. To 21.4 [basic.string], class template `basic_string` synopsis, add as indicated:

   >     basic_string& operator=(const basic_string& str);
   >     basic_string& operator=(basic_string&& str) noexcept;
   >     basic_string& operator=(const charT* s);
   >     basic_string& operator=(charT c);
   >     template <class IntT> basic_string& operator=(IntT i) = delete;
   >     basic_string& operator=(initializer_list<charT>);

2. Add after 21.4.2 [string.cons] p26 as indicated:

   >     basic_string& operator=(charT c);

   > > -26- Returns: `*this = basic_string(1,c)`.

   >     template <class IntT> basic_string& operator=(IntT i) = delete;

   > > -?- Remarks: This signature shall not participate in overload resolution unless `is_integral<T>::value` is `true`.

### 2373. Make new entities and names in namespace `std` conforming extensions

Section: 17.6.5 [conforming] Status: New Submitter: Chandler Carruth Opened: 2014-03-22 Last modified: 2014-06-17

View all other issues in [conforming].

View all issues with New status.

Discussion:

Technically, right now, it is not a conforming extension to add a new function to namespace `std`. Doing so could cause unqualified lookup on the name of that function in the presence of a using directive to find a different function. This seems an unreasonable restriction on library vendors providing conforming extensions, as such a using directive seems inherently risky in unqualified name lookup.

17.6.5.5 [member.functions] implies that adding overloads to a method is a conforming extension, and within some limits the same is true for global functions due to 17.6.5.4 [global.functions].

It would likely be useful to specify that other new entities are valid conforming extensions, or preclude them where they pose serious compatibility problems.

Proposed resolution:

### 2375. Is [iterator.requirements.general]/9 too broadly applied?

Section: 24.2.1 [iterator.requirements.general] Status: New Submitter: Marshall Clow Opened: 2014-03-25 Last modified: 2014-06-17

View all issues with New status.

Discussion:

24.2.1 [iterator.requirements.general] p9 says:

> Destruction of an iterator may invalidate pointers and references previously obtained from that iterator.

But the resolution of LWG issue 2360 specifically advocates returning `*--temp;` where `temp` is a local variable.

And 24.2.5 [forward.iterators] p6 says:

> If `a` and `b` are both dereferenceable, then `a == b` if and only if `*a` and `*b` are bound to the same object.

which disallows "stashing" iterators (i.e, iterators that refer to data inside themselves).

So, I suspect that the restriction in p9 should only apply to input iterators, and can probably be moved into 24.2.3 [input.iterators] instead of 24.2.1 [iterator.requirements.general].

[2014-05-22, Daniel comments]

Given that forward iterators (and beyond) are refinements of input iterator, moving this constraint to input iterators won't help much because it would still hold for all refined forms.

Proposed resolution:

### 2376. `bad_weak_ptr::what()` overspecified

Section: 20.8.2.1 [util.smartptr.weakptr] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2014-03-27 Last modified: 2014-05-02

View all issues with Tentatively Ready status.

Discussion:

20.8.2.1 [util.smartptr.weakptr] p2 requires `bad_weak_ptr` to return precisely the string `"bad_weak_ptr"`.

There was general agreement on the reflector and at the Issaquah meeting that this is over-constrained and implementation should be free to return something more descriptive if desired.

The proposed resolution makes `bad_weak_ptr` consistent with other exception types such as `bad_alloc` and `bad_cast`.

If accepted, the P/R for issue 2233, which currently uses similar wording to `bad_weak_ptr`, could be updated appropriately.

[2014-03-27 Library reflector vote]

The issue has been identified as Tentatively Ready based on six votes in favour.

Proposed resolution:

This wording is relative to N3936.

1. Edit 20.8.2.1 [util.smartptr.weakptr]:

   >     bad_weak_ptr() noexcept;

   > > -2- Postconditions: `what()` returns `"bad_weak_ptr"`an implementation-defined NTBS.

### 2377. `std::align` requirements overly strict

Section: 20.7.5 [ptr.align] Status: Ready Submitter: Peter Dimov Opened: 2014-03-30 Last modified: 2014-06-17

View all issues with Ready status.

Discussion:

`std::align` requires that its `alignment` argument shall be "a fundamental alignment value or an extended alignment value supported by the implementation in this context".

This requirement is overly strict. There are use cases that require a buffer aligned at values that are not tied to the C++ implementation, such as page size, cache line size, sector size. These come from the hardware or the OS and are generally not known until run time. The implementation of `std::align` does not depend on the requirement that `alignment` be a fundamental or an extended alignment value; any power of two would be handled the same way.

In addition, it is not possible for the user to even determine whether a value is "a fundamental alignment value or an extended alignment value supported by the implementation in this context". One would expect values coming from `alignof` to be fine, but I'm not sure whether even that is guaranteed in the presence of `alignas`.

Therefore, I propose that

> Requires:

> - `alignment` shall be a fundamental alignment value or an extended alignment value supported by the implementation in this context

be changed to

> Requires:

> - `alignment` shall be a power of two

[2014-06-16 Rapperswil]

Move to Ready

Proposed resolution:

This wording is relative to N3936.

1. Edit 20.7.5 [ptr.align] p2 as indicated:

   >     void* align(std::size_t alignment, std::size_t size,
   >       void*& ptr, std::size_t& space);

   > > -1- […]

   > > -2- Requires:

   > > - `alignment` shall be a fundamental alignment value or an extended alignment value supported by the implementation in this context power of two

### 2378. Behaviour of standard exception types

Section: 18.6.2.1 [bad.alloc], 18.6.2.2 [new.badlength], 18.7.2 [bad.cast], 18.7.3 [bad.typeid], 18.8.2 [bad.exception] Status: Review Submitter: Andy Sawyer Opened: 2014-03-31 Last modified: 2014-07-01

View all issues with Review status.

Discussion:

I think we have an issue with the specification of some of the standard exception types. In particular, several of them have default constructors with remarks to the effect that "The result of calling `what()` on the newly constructed object is implementation-defined". (In some cases this is contradictory to a further specification of `what()`, which is specified to return an implementation-defined NTBS.)

Previous resolution from Andy [SUPERSEDED]:

> This wording is relative to N3936.

> 1. Edit 18.6.2.1 [bad.alloc] p3 as indicated:

>    >     bad_alloc() noexcept;

>    > > […]

>    > > -3- Remarks: The result of calling `what()` on the newly constructed object is implementation-defined `what()` returns an implementation-defined NTBS.

> 2. Edit 18.6.2.2 [new.badlength] p3 as indicated: [Drafting note: Added the Postcondition, since we don't say anything else about `bad_array_new_length::what()` — end of note]

>    >     bad_array_new_length() noexcept;

>    > > […]

>    > > -3- Remarks Postcondition: The result of calling `what()` on the newly constructed object is implementation-defined `what()` returns an implementation-defined NTBS.

> 3. Edit 18.7.2 [bad.cast] p3 as indicated:

>    >     bad_cast() noexcept;

>    > > […]

>    > > -3- Remarks: The result of calling `what()` on the newly constructed object is implementation-defined..

> 4. Edit 18.7.3 [bad.typeid] p3 as indicated:

>    >     bad_typeid() noexcept;

>    > > […]

>    > > -3- Remarks: The result of calling `what()` on the newly constructed object is implementation-defined..

> 5. Edit 18.8.2 [bad.exception] p3 as indicated:

>    >     bad_exception() noexcept;

>    > > […]

>    > > -3- Remarks: The result of calling `what()` on the newly constructed object is implementation-defined..

[2014-06-17, Rapperswil]

Jonathan provides alternative wording.

Proposed resolution:

This wording is relative to N3936.

1. Edit 18.6.2.1 [bad.alloc] p3 as indicated:

   >     bad_alloc() noexcept;

   > > […]

   > > -3- Remarks: The result of calling `what()` on the newly constructed object is implementation-defined.

2. Edit 18.6.2.2 [new.badlength] as indicated:

   >     bad_array_new_length() noexcept;

   > > […]

   > > -3- Remarks: The result of calling `what()` on the newly constructed object is implementation-defined.

   >     virtual const char* what() const noexcept;

   > > -?- Returns: An implementation-defined NTBS.

3. Edit 18.7.2 [bad.cast] p3 as indicated:

   >     bad_cast() noexcept;

   > > […]

   > > -3- Remarks: The result of calling `what()` on the newly constructed object is implementation-defined..

4. Edit 18.7.3 [bad.typeid] p3 as indicated:

   >     bad_typeid() noexcept;

   > > […]

   > > -3- Remarks: The result of calling `what()` on the newly constructed object is implementation-defined..

5. Edit 18.8.2 [bad.exception] p3 as indicated:

   >     bad_exception() noexcept;

   > > […]

   > > -3- Remarks: The result of calling `what()` on the newly constructed object is implementation-defined..

### 2379. Obtaining native handle of the current thread

Section: 30.2.3 [thread.req.native], 30.3.2 [thread.thread.this] Status: New Submitter: Matt Austern Opened: 2014-03-31 Last modified: 2014-05-02

View all issues with New status.

Discussion:

Class `thread` contains an implementation-defined type `thread::native_handle_type`, and an implementation-defined function `thread::native_handle()` that returns a value of that type. The presence and semantics of those members is implementation-defined; the intention is that they can be used for interoperability with libraries that rely on operating system specific features. (Posix libraries that accept arguments of type `pthread_t`, for example.)

Unfortunately, there appears to be no native handle support for the equivalent of `pthread_self()`. We can use `this_thread::get_id()` to obtain the `thread::id` of the current thread, but there is no mechanism for converting a `thread::id` to a `thread::native_handle`.

Proposed wording:

In 30.3.2 [thread.thread.this] add:

>     thread::native_handle_type native_handle(); // See 30.2.3

to the `this_thread` namespace synopsis.

Rationale:

Informally, we could address this issue either by adding a new function in `this_thread` or by providing a mechanism for converting between `thread::id` and `thread::native_handle`. I propose the former because it seems more localized, and doesn't involve saying anything more about implementation defined native functionality than we currently do.

It's intentional that the proposed resolution adds a declaration of `native_handle()` without adding a paragraph explaining what it does. This is because everything about `native_handle()` is implementation-defined. The standard does the same thing in 30.3.1.5 [thread.thread.member].

Proposed resolution:

This wording is relative to N3936.

1. Change 30.2.3 [thread.req.native] p1 as indicated:

   > -1- Several classes described in this Clause have members This Clause includes several members named `native_handle_type` and `native_handle`. The presence of these members and their semantics is implementation-defined. […]

2. In 30.3 [thread.threads], header `<thread>` synopsis, add:

   >     namespace std {
   >       […]
   >       namespace this_thread {
   >         thread::id get_id() noexcept;
   >         thread::native_handle_type native_handle();
   >         […]
   >       }
   >     }

3. In 30.3.2 [thread.thread.this] add:

   >     namespace std {
   >       namespace this_thread {
   >         thread::id get_id() noexcept;
   >         thread::native_handle_type native_handle(); // See 30.2.3 [thread.req.native]
   >         […]
   >       }
   >     }

### 2380. May `<cstdlib>` provide `long ::abs(long)` and `long long ::abs(long long)`?

Section: 17.6.1.2 [headers] Status: Review Submitter: Richard Smith Opened: 2014-03-31 Last modified: 2014-07-01

View all other issues in [headers].

View all issues with Review status.

Discussion:

D.5 [depr.c.headers] p3 says:

> [Example: The header `<cstdlib>` assuredly provides its declarations and definitions within the namespace `std`. It may also provide these names within the global namespace. The header `<stdlib.h>` assuredly provides the same declarations and definitions within the global namespace, much as in the C Standard. It may also provide these names within the namespace `std`. — end example]

This suggests that `<cstdlib>` may provide `::abs(long)` and `::abs(long long)`. But this seems like it might contradict the normative wording of 17.6.1.2 [headers] p4:

> Except as noted in Clauses 18 through 30 and Annex D, the contents of each header `cname` shall be the same as that of the corresponding header `name.h`, as specified in the C standard library (1.2) or the C Unicode TR, as appropriate, as if by inclusion. In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace `std`. It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace `std` by explicit using-declarations (7.3.3).

Note that this allows `<cstdlib>` to provide `::abs(int)`, but does not obviously allow `::abs(long)` nor `::abs(long long)`, since they are not part of the header `stdlib.h` as specified in the C standard library.

26.8 [c.math] p7 adds signatures `std::abs(long)` and `std::abs(long long)`, but not in a way that seems to allow `::abs(long)` and `::abs(long long)` to be provided.

I think the right approach here would be to allow `<cstdlib>` to either provide no `::abs` declaration, or to provide all three declarations from namespace `std`, but it should not be permitted to provide only `int abs(int)`. Suggestion:

Change in 17.6.1.2 [headers] p4:

> […]. It is unspecified whether these names (including any overloads added in Clauses 18 through 30 and Annex D) are first declared within the global namespace scope and are then injected into namespace `std` by explicit using-declarations (7.3.3).

Proposed resolution:

This wording is relative to N3936.

1. Modify 17.6.1.2 [headers] p4 as indicated:

   > Except as noted in Clauses 18 through 30 and Annex D, the contents of each header `cname` shall be the same as that of the corresponding header `name.h`, as specified in the C standard library (1.2) or the C Unicode TR, as appropriate, as if by inclusion. In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace `std`. It is unspecified whether these names (including any overloads added in Clauses 18 through 30 and Annex D) are first declared within the global namespace scope and are then injected into namespace `std` by explicit using-declarations (7.3.3).

### 2381. Inconsistency in parsing floating point numbers

Section: 22.4.2.1.2 [facet.num.get.virtuals] Status: New Submitter: Marshall Clow Opened: 2014-04-30 Last modified: 2014-06-17

View other active issues in [facet.num.get.virtuals].

View all other issues in [facet.num.get.virtuals].

View all issues with New status.

Discussion:

In 22.4.2.1.2 [facet.num.get.virtuals] we have:

> Stage 3: The sequence of chars accumulated in stage 2 (the field) is converted to a numeric value by the rules of one of the functions declared in the header `<cstdlib>`:

> - For a signed integer value, the function `strtoll`.

> - For an unsigned integer value, the function `strtoull`.

> - For a floating-point value, the function `strtold`.

This implies that for many cases, this routine should return true:

>     bool is_same(const char* p)
>     {
>       std::string str{p};
>       double val1 = std::strtod(str.c_str(), nullptr);
>       std::stringstream ss(str);
>       double val2;
>       ss >> val2;
>       return std::isinf(val1) == std::isinf(val2) &&                 // either they're both infinity
>              std::isnan(val1) == std::isnan(val2) &&                 // or they're both NaN
>              (std::isinf(val1) || std::isnan(val1) || val1 == val2); // or they're equal
>     }

and this is indeed true, for many strings:

>     assert(is_same("0"));
>     assert(is_same("1.0"));
>     assert(is_same("-1.0"));
>     assert(is_same("100.123"));
>     assert(is_same("1234.456e89"));

but not for others

>     assert(is_same("0xABp-4")); // hex float
>     assert(is_same("inf"));
>     assert(is_same("+inf"));
>     assert(is_same("-inf"));
>     assert(is_same("nan"));
>     assert(is_same("+nan"));
>     assert(is_same("-nan"));

>     assert(is_same("infinity"));
>     assert(is_same("+infinity"));
>     assert(is_same("-infinity"));

These are all strings that are correctly parsed by `std::strtod`, but not by the stream extraction operators. They contain characters that are deemed invalid in stage 2 of parsing.

If we're going to say that we're converting by the rules of `strtold`, then we should accept all the things that `strtold` accepts.

Proposed resolution:

### 2382. Unclear order of container update versus object destruction on removing an object

Section: 17.6.5.8 [reentrancy] Status: Tentatively NAD Submitter: Peter Kasting Opened: 2014-05-06 Last modified: 2014-07-08

View other active issues in [reentrancy].

View all other issues in [reentrancy].

View all issues with Tentatively NAD status.

Discussion:

The standard does not seem to discuss reentrant access to a container during removal of an element, leaving it unclear whether a removed object is destroyed before or after it is removed from the container. For example, the behavior of the following code seems to be unspecified:

>     #include <iostream>
>     #include <map>
>     #include <memory>

>     struct T;
>     typedef std::map<int, std::shared_ptr<T>> TMap;

>     struct T {
>       T(TMap* t_map, int index) : t_map(t_map), index(index) {}
>       ~T() {
>         std::cout << "Object " << index << " is ";
>         if (t_map->count(index))
>           std::cout << "destroyed before being removed from the map" << std::endl;
>         else
>           std::cout << "removed from the map before being destroyed" << std::endl;
>       }

>       static void AddToMap(TMap* map, int index) {
>         (*map)[index] = std::make_shared<T>(map, index);
>       }

>       TMap* t_map;
>       int index;
>     };

>     int main()
>     {
>       TMap t_map;
>       T::AddToMap(&t_map, 0);
>       T::AddToMap(&t_map, 1);
>       t_map.erase(1);
>       t_map.erase(0);
>     }

The output of this program in Visual Studio 2013 is:

>     Object 1 is removed from the map before being destroyed
>     Object 0 is destroyed before being removed from the map

The core issue here is whether an object removed from a container should be destroyed before or after it is removed from the container. The current standard seems to be silent on this issue. The above output demonstrates that the behavior is actually inconsistent. (It's difficult to fully describe Visual Studio's behavior; for example, changing `main()` in the above example to the following:)

>     int main()
>     {
>       TMap t_map;
>       T::AddToMap(&t_map, 0);
>       T::AddToMap(&t_map, 1);
>       T::AddToMap(&t_map, 2);
>       T::AddToMap(&t_map, 3);
>       t_map.erase(3);
>       t_map.clear();
>     }

(...gives this output:)

>     Object 3 is removed from the map before being destroyed
>     Object 2 is destroyed before being removed from the map
>     Object 1 is destroyed before being removed from the map
>     Object 0 is removed from the map before being destroyed

In my opinion, the standard should explicitly describe when objects are destroyed as part of removal from a container. To me, it makes the most sense to say that objects should be removed from the container before they are destroyed.

[2014-05-07, Jeffrey Yasskin comments]

I think there are two main points here beyond this writeup:

1. We can't make recursive use of a standard library container valid in all cases.

2. If recursion through especially `erase()` is undefined behavior, that's pretty scary for existing large applications with code in destructors. Of course, "scary" doesn't mean we have to define the behavior.

I'll add a third: The language in 17.6.5.8 [reentrancy] nearly makes this undefined behavior already. I think any fix is probably going to live there, and extend the current "implementation-defined" on recursive reentrancy for individual functions to recursive reentrancy on class instances. I'm not sure exactly how to word that.

[2014-06 Rapperswil]

STL: We need more wording about how container methods can be reentrency.

Jeffrey: The title for this issue is confusing, what we really want is "reentrancy for objects".

Alisdair: Should we then close 2382 as NAD with a link to the new issue?

Proposed resolution:

### 2383. Overflow cannot be ill-formed for chrono::duration integer literals

Section: 20.12.5.8 [time.duration.literals] Status: New Submitter: Jonathan Wakely Opened: 2014-05-16 Last modified: 2014-06-17

View all issues with New status.

Discussion:

20.12.5.8 [time.duration.literals] p3 says:

> If any of these suffixes are applied to an integer literal and the resulting `chrono::duration` value cannot be represented in the result type because of overflow, the program is ill-formed.

Ill-formed requires a diagnostic at compile-time, but there is no way to detect the overflow from `unsigned long long` to the `signed duration<>::rep` type.

Overflow could be detected if the duration integer literals were literal operator templates, otherwise overflow can either be undefined or a run-time error, not ill-formed.

Proposed resolution:

### 2384. Allocator's `deallocate` function needs better specification

Section: 17.6.3.5 [allocator.requirements] Status: New Submitter: Daniel Krügler Opened: 2014-05-19 Last modified: 2014-06-17

View other active issues in [allocator.requirements].

View all other issues in [allocator.requirements].

View all issues with New status.

Discussion:

According to Table 28, 17.6.3.5 [allocator.requirements], an `Allocator`'s `deallocate` function is specified as follows:

> All `n` `T` objects in the area pointed to by `p` shall be destroyed prior to this call. `n` shall match the value passed to allocate to obtain this memory. Does not throw exceptions. [Note: `p` shall not be singular. — end note]

This wording is confusing in regard to the following points:

1. This specification does not make clear that the result of an `allocate` call can only be returned once to the `deallocate` function. This is much clearer expressed for `operator delete` (18.6.1.1 [new.delete.single] p12, emphasis mine):

   > Requires: `ptr` shall be a null pointer or its value shall be a value returned by an earlier call to the (possibly replaced) `operator new(std::size_t)` or `operator new(std::size_t,const std::nothrow_t&)` which has not been invalidated by an intervening call to `operator delete(void*)`.

2. The intended meaning of that wording was to say that `deallocate` shall accept every result value that had been returned by a corresponding call to `allocate`, this includes also a possible result of a null pointer value, which is possible ("[Note: If `n == 0`, the return value is unspecified. — end note]"). Unfortunately the `deallocate` function uses a non-normative note ("`p` shall not be singular.") which refers to the fuzzy term `singular`, that is one of the most unclear and misunderstood terms of the library, as pointed out in 1213. The occurrence of this term has lead to the possible understanding, that this function would never allow null pointer values. Albeit for allocators the intention had not been to require the support in general that a null pointer value can be provided to `deallocate` (as it is allowed for `std::free` and `operator delete`), the mental model was that every returned value of `allocate` shall be an acceptable argument type of the corresponding `deallocate` function.

This issue is not intending to enforce a specific meaning of singular iterator values, but the assertion is that this note does more harm than good. In addition to wording from `operator delete` there is no longer any need to obfuscate the normative wording.

[2014-05-24 Alisdair comments]

Now that I am reading it very precisely, there is another mis-stated assumption as a precondition for `deallocate`:

> All `n T` objects in the area pointed to by `p` shall be destroyed prior to this call.

This makes a poor assumption that every possible object in the allocated buffer was indeed constructed, but this is often not the case, e.g., a `vector` that is not filled to capacity. We should require calling the destructor for only those objects actually constructed in the buffer, which may be fewer than `n`, or even 0.

I wonder if we really require all objects to be destroyed before calling `deallocate` though. Are we really so concerned about leaking objects that might not manage resources? Should this not be the proper concern of the library managing the objects and memory?

[2014-06-05 Daniel responds and improves wording]

I fully agree with the last comment and I think that this requirement should be removed. We have no such requirements for comparable functions such as `operator delete` or `return_temporary_buffer()`, and this wording seems to be a wording rudiment that exists since C++98.

Proposed resolution:

This wording is relative to N3936.

1. Change Table 28 ("`Allocator` requirements") as indicated:

   > Table 28 — `Allocator` requirements
   > Expression | Return type | Assertion/note pre-/post-condition | Default
   > --- | --- | --- | ---
   > `…`
   > `a.deallocate(p,n)` | (not used) | Pre: `p` shall be a value returned by an earlier call to `allocate` which has not been invalidated by an intervening call to `deallocate`. `n` shall match the value passed to `allocate` to obtain this memory. All `n T` objects in the area pointed to by `p` shall be destroyed prior to this call. Throws: Nothing.`n` shall match the value passed to allocate to obtain this memory. Does not throw exceptions. [Note: `p` shall not be singular. — end note] |
   > `…`

### 2385. `function::assign` allocator argument doesn't make sense

Section: 20.9.11.2 [func.wrap.func] Status: New Submitter: Pablo Halpern Opened: 2014-05-23 Last modified: 2014-06-17

View other active issues in [func.wrap.func].

View all other issues in [func.wrap.func].

View all issues with New status.

Discussion:

The definition of `function::assign` in N3936 is:

>     template<class F, class A>
>       void assign(F&& f, const A& a);

> > Effects: `function(allocator_arg, a, std::forward<F>(f)).swap(*this)`

This definition is flawed in several respects:

1. The interface implies that the intent is to replace the allocator in `*this` with the specified allocator, `a`. Such functionality is unique in the standard and is problematic when creating, e.g. a container of function objects, all using the same allocator.

2. The current definition of `swap()` makes it unclear whether the objects being swapped can have different allocators. The general practice is that allocators must be equal in order to support swap, and this practice is reinforced by the proposed library TS. Thus, the definition of `assign` would have undefined behavior unless the allocator matched the allocator already within function.

3. The general rule for members of function is to supply the allocator before the functor, using the `allocator_arg` prefix. Supplying the allocator as a second argument, without the `allocator_arg` prefix is error prone and confusing.

I believe that this ill-conceived interface was introduced in the effort to add allocators to parts of the standard where it had been missing, when we were unpracticed in the right way to accomplish that. Allocators were added to function at a time when the allocator model was in flux and it was the first class in the standard after `shared_ptr` to use type-erased allocators, so it is not surprising to see some errors in specification here. (`shared_ptr` is a special case because of its shared semantics, and so is not a good model.)

The main question is whether this member should be specified with better precision or whether it should be deprecated/removed. The only way I can see to give a "reasonable" meaning to the existing interface is to describe it in terms of destroying and re-constructing `*this`:

>     function temp(allocator_arg, a, std::forward<F>(f));
>     this->~function();
>     ::new(this) function(std::move(temp));

(The temp variable is needed for exception safety). The ugliness of this specification underscores the ugliness of the concept. What is the purpose of this member other than to reconstruct the object from scratch, a facility that library classes do not generally provide? Programmers are always free to destroy and re-construct objects — there is no reason why function should make that especially easy.

I propose, therefore, that we make no attempt at giving the current interface a meaningful definition of questionable utility, but simply get rid of it all together. This leaves us with only two questions:

1. Should we deprecate the interface or just remove it?

2. Should we replace it with an `assign(f)` member that doesn't take an allocator?

Of these four combinations of binary answers to the above questions, I think the ones that make the most sense are (remove, no) and (deprecate, yes). The proposed new interface provides nothing that `operator=` does not already provide. However, if the old (deprecated) interface remains, then having the new interface will guide the programmer away from it.

The proposed wording below assumes deprecation. If we choose removal, then there is no wording needed; simply remove the offending declaration and definition.

Proposed resolution:

This wording is relative to N3936.

1. Change class template `function` synopsis, 20.9.11.2 [func.wrap.func], as indicated:

   >     template<class R, class... ArgTypes>
   >     class function<R(ArgTypes...)> {
   >       […]
   >       // 20.9.11.2.2, function modifiers:
   >       void swap(function&) noexcept;
   >       template<class F, class A> void assign(F&&, const A&);
   >       […]
   >     };

2. Change 20.9.11.2.2 [func.wrap.func.mod] as indicated:

   >     template<class F, class A> void assign(F&& f, const A& a);

   > > Effects: `*this = forward<F>(f);function(allocator_arg, a, std::forward<F>(f)).swap(*this)`

3. To deprecation section D.8 [depr.function.objects], add the following new sub-clause:

   > Old `assign` member of polymorphic function wrappers [depr.function.objects.assign]

   > >     namespace std{
   > >       template<class R, class... ArgTypes>
   > >       class function<R(ArgTypes...)> {
   > >         // remainder unchanged
   > >         template<class F, class A> void assign(F&& f, const A& a);
   > >         […]
   > >       };
   > >     }

   > The two-argument form of `assign` is defined as follows:

   >     template<class F, class A> void assign(F&& f, const A& a);

   > > Requires: `a` shall be equivalent to the allocator used to construct `*this`.

   > > Effects: `this->assign(forward<F>(f));`

### 2386. `function::operator=` handles allocators incorrectly

Section: 20.9.11.2.1 [func.wrap.func.con] Status: New Submitter: Pablo Halpern Opened: 2014-05-23 Last modified: 2014-06-17

View all other issues in [func.wrap.func.con].

View all issues with New status.

Discussion:

The Effects clauses for the assignment operator for class template `function` are written as code that constructs a temporary `function` and then swaps it with `*this`. The intention appears to be that assignment should have the strong exception guarantee, i.e., `*this` is not modified if an exception is thrown. However, the current description is incorrect when `*this` was constructed using an allocator.

Part of the problem is the under-specification of `swap`, which does not state the allocator requirements or allocator postconditions. If `swap` behaves like the rest of the standard library, swapping function objects constructed with different allocators would be undefined behavior. Alternatively `swap` could exchange the allocators, though I would argue against this specification.

For either specification of `swap`, the current Effects clauses for `operator=` are incorrect. If `swap` does not exchange the allocators, then `operator=` would have undefined behavior, which is clearly not desired. If `swap` does exchange the allocators, then `operator=` would always leave the left-hand side (lhs) of the assignment with a default allocator. The latter would be surprising behavior, as the allocator instance is normally unchanged for the lifetime of an object (for good reason), and is certainly not reset to default arbitrarily.

The desired behavior is that assignment would leave the allocator of the lhs unchanged. The way to achieve this behavior is to construct the temporary `function` using the original allocator. Unfortunately, we cannot describe the desired behavior in pure code, because there is no way to name the type-erased value of the allocator. (N3916 would improve this situation for the Library Fundamentals TS, but even with those changes, there is no way to recover the original type of the allocator.) The PR below, therefore, uses pseudo-code, inventing a fictitious `ALLOCATOR_OF(f)` expression that evaluates to the actual allocator type, even if that allocator was type erased. I have implemented this PR successfully.

Proposed resolution:

This wording is relative to N3936.

1. Change 20.9.11.2.1 [func.wrap.func.con] as indicated:

   > In the following descriptions, `ALLOCATOR_OF(f)` is a copy of the allocator specified in the construction of `function` `f`, or `allocator<char>()` if no allocator was specified.

   >     function& operator=(const function& f);

   > > -12- Effects: `function(allocator_arg, ALLOCATOR_OF(*this), f).swap(*this);`

   > > -13- Returns: `*this`

   >     function& operator=(function&& f);

   > > -14- Effects: Replaces the target of `*this` with the target of `f`.`function(allocator_arg, ALLOCATOR_OF(*this), std::move(f)).swap(*this);`

   > > -15- Returns: `*this`

   >     function& operator=(nullptr_t);

   > > -16- Effects: If `*this != nullptr`, destroys the target of `this`.

   > > -17- Postconditions: `!(*this)`. The allocator is unchanged.

   > > -18- Returns: `*this`

   > > -?- Throws: Nothing.

   >     template<class F> function& operator=(F&& f);

   > > -19- Effects: `function(allocator_arg, ALLOCATOR_OF(*this), std::forward<F>(f)).swap(*this);`

   > > -20- Returns: `*this`

   > > -21- Remarks: This assignment operator shall not participate in overload resolution unless `declval<typename decay<F>::type&>()` is `Callable` (20.9.11.2) for argument types `ArgTypes...` and return type `R`.

   >     template<class F> function& operator=(reference_wrapper<F> f);

   > > -22- Effects: `function(allocator_arg, ALLOCATOR_OF(*this), f).swap(*this);`

   > > -23- Returns: `*this`

### 2387. More nested types that must be accessible and unambiguous

Section: 20.9.2 [func.require], 20.9.3 [refwrap] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2014-05-23 Last modified: 2014-06-17

View other active issues in [func.require].

View all other issues in [func.require].

View all issues with Tentatively Ready status.

Discussion:

Further to 2299 and 2361, 20.9.2 [func.require] p3 and 20.9.3 [refwrap] p3 and p4 talk about member types without any mention of being accessible and unambiguous.

[2014-06-05 Daniel provides wording]

[2014-06-06 Library reflector vote]

The issue has been identified as Tentatively Ready based on six votes in favour.

Proposed resolution:

This wording is relative to N3936.

1. Change 20.9.2 [func.require] p3 as indicated:

   > -3- If a call wrapper (20.9.1) has a weak result type the type of its member type `result_type` is based on the type `T` of the wrapper's target object (20.9.1):

   > - if `T` is a pointer to function type, `result_type` shall be a synonym for the return type of `T`;

   > - if `T` is a pointer to member function, `result_type` shall be a synonym for the return type of `T`;

   > - if `T` is a class type and the qualified-id `T::result_type` is valid and denotes a type (14.8.2 [temp.deduct])with a member type `result_type`, then `result_type` shall be a synonym for `T::result_type`;

   > - otherwise `result_type` shall not be defined.

2. Change 20.9.3 [refwrap] p3+p4 as indicated:

   > -3- The template instantiation `reference_wrapper<T>` shall define a nested type named `argument_type` as a synonym for `T1` only if the type `T` is any of the following:

   > - a function type or a pointer to function type taking one argument of type `T1`

   > - a pointer to member function `R T0::f` cv (where cv represents the member function_s cv-qualifiers); the type `T1` is cv `T0*`

   > - a class type where the qualified-id `T::argument_type` is valid and denotes a type (14.8.2 [temp.deduct])with a member type `argument_type`; the type `T1` is `T::argument_type`.

   > -4- The template instantiation `reference_wrapper<T>` shall define two nested types named `first_argument_type` and `second_argument_type` as synonyms for `T1` and `T2`, respectively, only if the type `T` is any of the following:

   > - a function type or a pointer to function type taking two arguments of types `T1` and `T2`

   > - a pointer to member function `R T0::f(T2)` cv (where cv represents the member function's cv-qualifiers); the type `T1` is cv `T0*`

   > - a class type where the qualified-ids `T::first_argument_type` and `T::second_argument_type` are both valid and both denote types (14.8.2 [temp.deduct])with member types `first_argument_type` and `second_argument_type`; the type `T1` is `T::first_argument_type`. and the type `T2` is `T::second_argument_type`.

### 2388. Handling self-assignment in the proposed library function `std::exchange`

Section: 20.2.3 [utility.exchange] Status: New Submitter: Nick Calus Opened: 2014-05-09 Last modified: 2014-06-17

View all other issues in [utility.exchange].

View all issues with New status.

Discussion:

In paper N3668, the addition of a template function `std::exchange` had been proposed. In the rationale provided by the paper, we find the following:

> I chose the name for symmetry with `atomic_exchange`, since they behave the same except for this function not being atomic.

and:

> Atomic objects provide an `atomic_exchange` function ([atomics.types.operations.req]p18) that assigns a new value to the object and returns the old value. This operation is also useful on non-atomic objects, and this paper proposes adding it to the library.

> But the specified semantics of `std::exchange` is defined as follows:

>     template <class T, class U=T> T exchange(T& obj, U&& new_val);

> > Effects: Equivalent to:

> > >     T old_val = std::move(obj);
> > >     obj = std::forward<U>(new_val);
> > >     return old_val;

When looking at the post-condition of the `std::exchange` function, one would expect the return value to be the old value of `obj` and also that `obj` now contains the value of `new_value`. This post-condition is violated when `obj` is a reference to the same object as `new_value` and type `T` has move semantics.

Given it's specification, it is clear that `std::exchange` is meant to be used with types that have move semantics. Therefore, the post-condition is violated for self-assignments.

Suppose the following situation:

You have a vector of objects. The objects implement move semantics and are emptied when moved from. You provide a function that allows you to replace an object at a specific index by a new object (provided by reference as an argument to your function). When replacing an object, your function calls a member-function `do_something_fancy` on the old object.

>     void your_function(int i, X& new_val) {
>       std::exchange(vec[i], new_val).do_something_fancy();
>     }

Your function gets called with a given index and the corresponding element of said vector. (by coincidence or by purpose, it doesn't really matter)

>     your_function(5, vec[5]);

This will cause the object at `vec[5]` to be in an empty state. If this object would not implement move semantics, assignment performance is potentially worse, but at least it is not in an empty (to my business logic, invalid) state.

So to me, the current reference implementation of `std::exchange` does not have the behavior it is expected to have.

Proposed resolution:

This wording is relative to N3936.

1. Change 20.2.3 [utility.exchange] as indicated:

   >     template <class T, class U=T> T exchange(T& obj, U&& new_val);

   > > -1- Effects: Equivalent to:

   > > >     T tmp = std::forward<U>(new_val);
   > > >     T old_val = std::move(obj);
   > > >     obj = std::forward<U>(new_val)std::move(tmp);
   > > >     return old_val;

### 2391. `basic_string` is missing non-`const` `data()`

Section: 21.4 [basic.string] Status: New Submitter: Michael Bradshaw Opened: 2014-05-27 Last modified: 2014-06-17

View other active issues in [basic.string].

View all other issues in [basic.string].

View all issues with New status.

Discussion:

Regarding 21.4 [basic.string], `std::basic_string<charT>::data()` returns a `const charT*` 21.4.7.1 [string.accessors]. While this method is convenient, it doesn't quite match `std::array<T>::data()` 23.3.2.5 [array.data] or `std::vector<T>::data()` 23.3.6.4 [vector.data], both of which provide two versions (that return `T*` or `const T*`). An additional `data()` method can be added to `std::basic_string` that returns a `charT*` so it can be used in similar situations that `std::array` and `std::vector` can be used. Without a non-`const` `data()` method, `std::basic_string` has to be treated specially in code that is otherwise oblivious to the container type being used.

Adding a `charT*` return type to `data()` would be equivalent to doing `&str[0]` or `&str.front()`.

Small discussion on the issue can be found here and in the std-discussion thread (which didn't get too much attention).

This requires a small change to `std::basic_string`'s definition in 21.4 [basic.string] to add the method to `std::basic_string`, and another small change in 21.4.7.1 [string.accessors] to define the new method.

Proposed resolution:

This wording is relative to N3936.

1. Change class template `basic_string` synopsis, 21.4 [basic.string], as indicated:

   >     namespace std {
   >       template<class charT, class traits = char_traits<charT>,
   >       class Allocator = allocator<charT> >
   >       class basic_string {
   >       public:
   >         […]
   >         // 21.4.7, string operations:
   >         const charT* c_str() const noexcept;
   >         const charT* data() const noexcept;
   >         charT* data() noexcept;
   >         allocator_type get_allocator() const noexcept;
   >         […]
   >       };
   >     }

2. Add the following sequence of paragraphs following 21.4.7.1 [string.accessors] p3, as indicated:

   >     charT* data() noexcept;

   > > -?- Returns: A pointer `p` such that `p + i == &operator[](i)` for each `i` in `[0,size()]`.

   > > -?- Complexity: Constant time.

   > > -?- Requires: The program shall not alter the value stored at `p + size()`.

### 2392. "character type" is used but not defined

Section: 17.3.17 [defns.ntcts], 22.3.1.1.1 [locale.category], 27.2.2 [iostreams.limits.pos], 27.7.3.6.1 [ostream.formatted.reqmts], 27.7.3.6.4 [ostream.inserters.character] Status: New Submitter: Jeffrey Yasskin Opened: 2014-06-01 Last modified: 2014-06-17

View all issues with New status.

Discussion:

The term "character type" is used in 17.3.17 [defns.ntcts], 22.3.1.1.1 [locale.category], 27.2.2 [iostreams.limits.pos], 27.7.3.6.1 [ostream.formatted.reqmts], and 27.7.3.6.4 [ostream.inserters.character], but the core language only defines "narrow character types" (3.9.1 [basic.fundamental]).

"wide-character type" is used in 22.5 [locale.stdcvt], but the core language only defines a "wide-character set" and "wide-character literal".

Proposed resolution:

### 2393. `std::function`'s Callable definition is broken

Section: 20.9.11.2 [func.wrap.func] Status: New Submitter: Daniel Krügler Opened: 2014-06-03 Last modified: 2014-06-17

View other active issues in [func.wrap.func].

View all other issues in [func.wrap.func].

View all issues with New status.

Discussion:

The existing definition of `std::function`'s Callable requirements provided in 20.9.11.2 [func.wrap.func] p2,

> A callable object `f` of type `F` is Callable for argument types `ArgTypes` and return type `R` if the expression `INVOKE(f, declval<ArgTypes>()..., R)`, considered as an unevaluated operand (Clause 5), is well formed (20.9.2).

is defective in several aspects:

1. The wording can be read to be defined in terms of callable objects, not of callable types.

2. Contrary to that, 20.9.11.2.5 [func.wrap.func.targ] p2 speaks of "`T` shall be a type that is Callable (20.9.11.2) for parameter types `ArgTypes` and return type `R`."

3. The required value category of the callable object during the call expression (lvalue or rvalue) strongly depends on an interpretation of the expression `f` and therefore needs to be specified unambiguously.

The intention of original proposal (see IIIa. Relaxation of target requirements) was to refer to both types and values ("we say that the function object `f` (and its type `F`) is Callable […]"), but that mental model is not really deducible from the existing wording. An improved type-dependence wording would also make the sfinae-conditions specified in 20.9.11.2.1 [func.wrap.func.con] p8 and p21 ("[…] shall not participate in overload resolution unless `f` is Callable (20.9.11.2) for argument types `ArgTypes...` and return type `R`.") easier to interpret.

My understanding always had been (see e.g. Howard's code example in the 2009-05-01 comment in LWG 815), that `std::function` invokes the call operator of its target via an lvalue. The required value-category is relevant, because it allows to reflect upon whether an callable object such as

>     struct RVF
>     {
>       void operator()() const && {}
>     };

would be a feasible target object for `std::function<void()>` or not.

Clarifying the current Callable definition seems also wise to make a future transition to language-based concepts easier. A local fix of the current wording is simple to achieve, e.g. by rewriting it as follows:

> A callable object `f` of type (20.9.1 [func.def]) `F` is Callable for argument types `ArgTypes` and return type `R` if the expression `INVOKE(fdeclval<F&>(), declval<ArgTypes>()..., R)`, considered as an unevaluated operand (Clause 5), is well formed (20.9.2).

It seems appealing to move such a general Callable definition to a more "fundamental" place (e.g. as another paragraph of 20.9.1 [func.def]), but the question arises, whether such a more general concept should impose the requirement that the call expression is invoked on an lvalue of the callable object — such a special condition would also conflict with the more general definition of the `result_of` trait, which is defined for either lvalues or rvalues of the callable type `Fn`. In this context I would like to point out that "Lvalue-Callable" is not the one and only Callable requirement in the library. Counter examples are `std::thread`, `call_once`, or `async`, which depend on "Rvalue-Callable", because they all act on functor rvalues, see e.g. 30.3.1.2 [thread.thread.constr]:

> […] The new thread of execution executes `INVOKE(DECAY_COPY(std::forward<F>(f)), DECAY_COPY(std::forward<Args>(args))...)` […]

For every callable object `F`, the result of `DECAY_COPY` is an rvalue. These implied rvalue function calls are no artifacts, but had been deliberately voted for by a Committee decision (see LWG 2021, 2011-06-13 comment) and existing implementations respect these constraints correctly. Just to give an example,

>     #include <thread>

>     struct LVF
>     {
>       void operator()() & {}
>     };

>     int main()
>     {
>       LVF lf;
>       std::thread t(lf);
>       t.join();
>     }

is supposed to be rejected.

The below presented wording changes are suggested to be minimal (still local to `std::function`), but the used approach would simplify a future (second) conceptualization or any further generalization of Callable requirements of the Library.

Proposed resolution:

This wording is relative to N3936.

1. Change 20.9.11.2 [func.wrap.func] p2 as indicated:

   > -2- A callable object `f` of type (20.9.1 [func.def]) `F` is Lvalue-Callable for argument types `ArgTypes` and return type `R` if the expression `INVOKE(fdeclval<F&>(), declval<ArgTypes>()..., R)`, considered as an unevaluated operand (Clause 5), is well formed (20.9.2).

2. Change 20.9.11.2.1 [func.wrap.func.con] p8+p21 as indicated:

   >     template<class F> function(F f);
   >     template <class F, class A> function(allocator_arg_t, const A& a, F f);

   > > […]

   > > -8- Remarks: These constructors shall not participate in overload resolution unless `fF` is `Lvalue-Callable` (20.9.11.2) for argument types `ArgTypes...` and return type `R`.

   > […]

   >     template<class F> function& operator=(F&& f);

   > > […]

   > > -21- Remarks: This assignment operator shall not participate in overload resolution unless `declval<typename decay<F>::type&>()decay_t<F>` is `Lvalue-Callable` (20.9.11.2) for argument types `ArgTypes...` and return type `R`.

3. Change 20.9.11.2.5 [func.wrap.func.targ] p2 as indicated: [Editorial comment: Instead of adapting the preconditions for the naming change I recommend to strike it completely, because the `target()` functions do not depend on it; the corresponding wording exists since its initial proposal and it seems without any advantage to me. Assume that some template argument `T` is provided, which does not satisfy the requirements: The effect will be that the result is a null pointer value, but that case can happen in other (valid) situations as well. — end comment]

   >     template<class T> T* target() noexcept;
   >     template<class T> const T* target() const noexcept;

   > > -2- Requires: `T` shall be a type that is `Callable` (20.9.11.2) for parameter types `ArgTypes` and return type `R`.

   > > -3- Returns: If `target_type() == typeid(T)` a pointer to the stored function target; otherwise a null pointer.

### 2394. `locale::name` specification unclear — what is implementation-defined?

Section: 22.3.1.3 [locale.members] Status: New Submitter: Richard Smith Opened: 2014-06-09 Last modified: 2014-06-17

View all other issues in [locale.members].

View all issues with New status.

Discussion:

22.3.1.3 [locale.members] p5 says:

> Returns: The name of `*this`, if it has one; otherwise, the string `"*"`. If `*this` has a name, then `locale(name().c_str())` is equivalent to `*this`. Details of the contents of the resulting string are otherwise implementation-defined.

So… what is implementation-defined here, exactly? The first sentence completely defines the behavior of this function in all cases.

Also, the second sentence says (effectively) that all locales with the same name are equivalent: given `L1` and `L2` that have the same name `N`, they are both equivalent to `locale(N)`, and since there is no definition of "equivalent" specific to `locale`, I assume it's the normal transitive equivalence property, which would imply that `L1` is equivalent to `L2`. I'm not sure why this central fact is in the description of `locale::name`, nor why it's written in this roundabout way.

Proposed resolution:

### 2396. `underlying_type` doesn't say what to do for an incomplete enumeration type

Section: 20.10.7.6 [meta.trans.other] Status: Ready Submitter: Richard Smith Opened: 2014-06-12 Last modified: 2014-06-17

View other active issues in [meta.trans.other].

View all other issues in [meta.trans.other].

View all issues with Ready status.

Discussion:

Consider:

>     enum E {
>       e = std::underlying_type<E>::type(1)
>     };

Clearly this should be ill-formed, but the library section doesn't appear to ban it. Suggestion:

Change in 20.10.7.6 [meta.trans.other] Table 57:

> Template: `template<class T> struct underlying_type;`

> Condition: `T` shall be a complete an enumeration type (7.2)

> Comments: […]

[2014-06-16 Rapperswil]

Move to Ready

Proposed resolution:

This wording is relative to N3936.

1. Change Table 57 — "Other transformations" as indicated:

> Table 3 — Other type transformations
> Template | Condition | Comments
> --- | --- | ---
> `…`
> `template <class T> struct underlying_type;` | T shall be a complete an enumeration type (7.2) | […]

### 2397. `map<K, V>::emplace` and explicit `V` constructors

Section: 20.10.7.6 [meta.trans.other] Status: Open Submitter: Peter Dimov Opened: 2014-06-12 Last modified: 2014-06-23

View other active issues in [meta.trans.other].

View all other issues in [meta.trans.other].

View all issues with Open status.

Discussion:

Please consider the following example:

>     #include <map>
>     #include <atomic>

>     int main()
>     {
>        std::map<int, std::atomic<int>> map_;

>        map_.emplace(1, 0);  // fail
>        map_.emplace(1);     // fail
>        map_.emplace(1, {}); // fail

>        map_.emplace(std::piecewise_construct,
>            std::tuple<int>(1), std::tuple<>()); // OK
>     }

The first three calls represent attempts by an ordinary programmer (in which role I appear today) to construct a map element. Since `std::atomic<int>` is non-copyable and immovable, I was naturally drawn to `emplace()` because it constructs in-place and hence doesn't need to copy or move. The logic behind the attempts was that `K=int` would be constructed from '`1`', and `V=std::atomic<int>` would be (directly) constructed by '`0`', default constructed, or constructed by '`{}`'.

Yet none of the obvious attempts worked.

I submit that at least two of the three ought to have worked, and that we have therefore a defect in either `map::emplace` or `pair`.

Ville:

There exists a related EWG issue for this.

Daniel:

If the proposal N3739 would be accepted, it would solve the problem mentioned here.

Proposed resolution:

### 2398. `type_info`'s destructor shouldn't be required to be virtual

Section: 18.7.1 [type.info] Status: New Submitter: Stephan T. Lavavej Opened: 2014-06-14 Last modified: 2014-06-17

View all other issues in [type.info].

View all issues with New status.

Discussion:

`type_info`'s destructor is depicted as being `virtual`, which is nearly unobservable to users (since they can't construct or copy this class, they can't usefully derive from it). However, it's technically observable (via `is_polymorphic` and `has_virtual_destructor`). It also imposes real costs on implementations, requiring them to store one vptr per `type_info` object, when RTTI space consumption is a significant concern.

Making this implementation-defined wouldn't affect users (who can observe this only if they're specifically looking for it) and wouldn't affect implementations who need `virtual` here, but it would allow other implementations to drop `virtual` and improve their RTTI space consumption.

Richard Smith:

It's observable in a few other ways.

>     std::map<void*, something> m;
>     m[dynamic_cast<void*>(&typeid(blah))] = stuff;

... is broken by this change, because you can't `dynamic_cast` a non-polymorphic class type to `void*`.

>     type_info& f();
>     typeid(f());

... evaluates `f()` at runtime without this change, and might not do so with this change.

These are probably rare things, but I can imagine at least some forms of the latter being used in SFINAE tricks.

Proposed resolution:

This wording is relative to N3936.

1. Change 18.7.1 [type.info] as indicated:

   >     namespace std {
   >       class type_info {
   >       public:
   >         virtualsee below ~type_info();
   >         […]
   >       };
   >     }

   > -1- The class `type_info` describes type information generated by the implementation. Objects of this class effectively store a pointer to a name for the type, and an encoded value suitable for comparing two types for equality or collating order. The names, encoding rule, and collating sequence for types are all unspecified and may differ between programs. Whether `~type_info()` is `virtual` is implementation-defined.

### 2399. `shared_ptr`'s constructor from `unique_ptr` should be constrained

Section: 20.8.2.2.1 [util.smartptr.shared.const] Status: Ready Submitter: Stephan T. Lavavej Opened: 2014-06-14 Last modified: 2014-06-17

View other active issues in [util.smartptr.shared.const].

View all other issues in [util.smartptr.shared.const].

View all issues with Ready status.

Discussion:

Consider the following code:

>     #include <iostream>
>     #include <memory>
>     #include <string>

>     using namespace std;

>     void meow(const shared_ptr<int>& sp) {
>       cout << "int: " << *sp << endl;
>     }

>     void meow(const shared_ptr<string>& sp) {
>       cout << "string: " << *sp << endl;
>     }

>     int main() {
>       meow(make_unique<int>(1729));
>       meow(make_unique<string>("kitty"));
>     }

This fails to compile due to ambiguous overload resolution, but we can easily make this work. (Note: `shared_ptr`'s constructor from `auto_ptr` is also affected, but I believe that it's time to remove `auto_ptr` completely.)

[2014-06-16 Rapperswil]

Move to Ready

Proposed resolution:

This wording is relative to N3936.

1. Change 20.8.2.2.1 [util.smartptr.shared.const] around p33 as indicated:

   >     template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);

   > -?- Remark: This constructor shall not participate in overload resolution unless `unique_ptr<Y, D>::pointer` is convertible to `T*`.

   > -33- Effects: Equivalent to `shared_ptr(r.release(), r.get_deleter())` when `D` is not a reference type, otherwise `shared_ptr(r.release(), ref(r.get_deleter()))`.

### 2400. `shared_ptr`'s `get_deleter()` should use `addressof()`

Section: 20.8.2.2.10 [util.smartptr.getdeleter] Status: Ready Submitter: Stephan T. Lavavej Opened: 2014-06-14 Last modified: 2014-06-17

View all other issues in [util.smartptr.getdeleter].

View all issues with Ready status.

Discussion:

The Standard Library should consistently use `addressof()` to defend itself against overloaded `operator&()`.

While we're in the neighbourhood, we should editorially change `0` to `nullptr`.

[2014-06-16 Rapperswil]

Move to Ready

Proposed resolution:

This wording is relative to N3936.

1. Change 20.8.2.2.10 [util.smartptr.getdeleter] as indicated:

   >     template <class D, class T> get_deleter(const shared_ptr<T>& p) noexcept;

   > -1- Returns: If `p` owns a deleter `d` of type cv-unqualified `D`, returns `&std::addressof(d)`; otherwise returns `0nullptr`. […]

### 2401. `std::function` needs more `noexcept`

Section: 20.9.11.2 [func.wrap.func] Status: Ready Submitter: Stephan T. Lavavej Opened: 2014-06-14 Last modified: 2014-06-17

View other active issues in [func.wrap.func].

View all other issues in [func.wrap.func].

View all issues with Ready status.

Discussion:

There are two issues here:

1. `std::function`'s constructor from `nullptr_t` is marked as `noexcept`, but its assignment operator from `nullptr_t` isn't. This assignment can and should be marked as `noexcept`.

2. `std::function`'s comparisons with `nullptr_t` are marked as `noexcept` in two out of three places.

[2014-06-16 Rapperswil]

Move to Ready

Proposed resolution:

This wording is relative to N3936.

1. Change 20.9 [function.objects] p2, header `<functional>` synopsis, as indicated:

   >     namespace std {
   >       […]
   >       // 20.9.11 polymorphic function wrappers:
   >       […]
   >       template<class R, class... ArgTypes>
   >       bool operator==(const function<R(ArgTypes...)>&, nullptr_t) noexcept;
   >       template<class R, class... ArgTypes>
   >       bool operator==(nullptr_t, const function<R(ArgTypes...)>&) noexcept;
   >       template<class R, class... ArgTypes>
   >       bool operator!=(const function<R(ArgTypes...)>&, nullptr_t) noexcept;
   >       template<class R, class... ArgTypes>
   >       bool operator!=(nullptr_t, const function<R(ArgTypes...)>&) noexcept;
   >       […]
   >     }

2. Change 20.9.11.2 [func.wrap.func], class template `function` synopsis, as indicated:

   >     […]
   >     // 20.9.11.2.1, construct/copy/destroy:
   >     […]
   >     function& operator=(nullptr_t) noexcept;
   >     […]

3. Change 20.9.11.2.1 [func.wrap.func.con] before p16 as indicated:

   >     function& operator=(nullptr_t) noexcept;

### 2402. `basic_string(const basic_string& str, size_type pos, size_type n = npos)` shouldn't use `Allocator()`

Section: 21.4.2 [string.cons] Status: New Submitter: Stephan T. Lavavej Opened: 2014-06-14 Last modified: 2014-06-17

View other active issues in [string.cons].

View all other issues in [string.cons].

View all issues with New status.

Discussion:

21.4.2 [string.cons] p3 specifies:

>     basic_string(const basic_string& str, size_type pos, size_type n = npos, const Allocator& a = Allocator());

> But this implies that `basic_string(str, pos)` and `basic_string(str, pos, n)` use `Allocator()` instead of getting an allocator from `str`.

> 21.4.1 [string.require] p3 says "The `Allocator` object used shall be obtained as described in 23.2.1." 23.2.1 [container.requirements.general] p8 says "Copy constructors for these container types obtain an allocator by calling `allocator_traits<allocator_type>::select_on_container_copy_construction` on the allocator belonging to the container being copied.", but this isn't exactly a copy constructor. Then it talks about move constructors (which this definitely isn't), and finally says that "All other constructors for these container types take a `const allocator_type&` argument. […] A copy of this allocator is used for any memory allocation performed".

Proposed resolution:

This wording is relative to N3936.

1. Change 21.4 [basic.string] p5, class template `basic_string` synopsis, as indicated:

   >     […]
   >     // 21.4.2, construct/copy/destroy:
   >     […]
   >     basic_string(basic_string&& str) noexcept;
   >     basic_string(const basic_string& str, size_type pos, size_type n = npos);
   >     basic_string(const basic_string& str, size_type pos, size_type n = npos,
   >                 const Allocator& a = Allocator());
   >     […]

2. Change 21.4.2 [string.cons] around p3 as indicated:

   >     basic_string(const basic_string& str,
   >                  size_type pos, size_type n = npos);
   >     basic_string(const basic_string& str,
   >                  size_type pos, size_type n = npos,
   >                  const Allocator& a = Allocator());

   > > […]

   > > -5- Effects: Constructs an object of class `basic_string` and determines the effective length `rlen` of the initial string value as the smaller of `n` and `str.size() - pos`, as indicated in Table 65. The first constructor obtains an allocator by calling `allocator_traits<allocator_type>::select_on_container_copy_construction` on the allocator belonging to `str`.

   > > Table 65 — `basic_string(const basic_string&, size_type, size_type)` and `basic_string(const basic_string&, size_type, size_type, const Allocator&)` effects

### 2403. `stof()` should call `strtof()` and `wcstof()`

Section: 21.5 [string.conversions] Status: New Submitter: Stephan T. Lavavej Opened: 2014-06-14 Last modified: 2014-07-01

View all other issues in [string.conversions].

View all issues with New status.

Discussion:

`stof()` is currently specified to call `strtod()`/`wcstod()` (which converts the given string to `double`) and then it's specified to convert that `double` to `float`. This performs rounding twice, which introduces error. Here's an example written up by James McNellis:

Consider the following number `X`:

>     1.999999821186065729339276231257827021181583404541015625 (X)

This number is exactly representable in binary as:

>     1.111111111111111111111101000000000000000000000000000001
>     * ^1st                  ^23rd                        ^52nd

I've marked the 23rd and 52nd fractional bits. These are the least significant bits for `float` and `double`, respectively.

If we convert this number directly to `float`, we take the 23 most significant bits:

>     1.11111111111111111111110

The next bit is a one and the tail is nonzero (the 54th fractional bit is a one), so we round up. This gives us the correctly rounded result:

>     1.11111111111111111111111

So far so good. But... If we convert `X` to `double`, we take the 52 most significant bits:

>     1.1111111111111111111111010000000000000000000000000000 (Y)

The next bit is a zero, so we round down (truncating the value). If we then convert `Y` to `float`, we take its 23 most significant bits:

>     1.11111111111111111111110

The next bit is a one and the tail is zero, so we round to even (leaving the value unchanged). This is off by 1ulp from the correctly rounded result.

[2014-06 Rapperswil]

Marshall Clow will look at this.

Proposed resolution:

This wording is relative to N3936.

1. Change 21.5 [string.conversions] p4+p6 as indicated:

   >     float stof(const string& str, size_t* idx = 0);
   >     double stod(const string& str, size_t* idx = 0);
   >     long double stold(const string& str, size_t* idx = 0);

   > > -4- Effects: the first two These functions call `strtof(str.c_str(), ptr)`, `strtod(str.c_str(), ptr)`, and the third function calls `strtold(str.c_str(), ptr)`, respectively. Each function returns the converted result, if any. […]

   > > […]

   > > -6- Throws: `invalid_argument` if `strtof`, `strtod`, or `strtold` reports that no conversion could be performed. Throws `out_of_range` if `strtof`, `strtod`, or `strtold` sets `errno` to `ERANGE` or if the converted value is outside the range of representable values for the return type.

2. Change 21.5 [string.conversions] p11+p13 as indicated:

   >     float stof(const wstring& str, size_t* idx = 0);
   >     double stod(const wstring& str, size_t* idx = 0);
   >     long double stold(const wstring& str, size_t* idx = 0);

   > > -11- Effects: the first two These functions call `wcstof(str.c_str(), ptr)`, `wcstod(str.c_str(), ptr)`, and the third function calls `wcstold(str.c_str(), ptr)`, respectively. Each function returns the converted result, if any. […]

   > > […]

   > > -13- Throws: `invalid_argument` if `wcstof`, `wcstod`, or `wcstold` reports that no conversion could be performed. Throws `out_of_range` if `wcstof`, `wcstod`, or `wcstold` sets `errno` to `ERANGE`.

### 2404. `mismatch()`'s complexity needs to be updated

Section: 25.2.10 [mismatch] Status: Ready Submitter: Stephan T. Lavavej Opened: 2014-06-14 Last modified: 2014-06-17

View all issues with Ready status.

Discussion:

N3671 updated the complexities of `equal()` and `is_permutation()`, but not `mismatch()`.

[2014-06-16 Rapperswil]

Move to Ready

Proposed resolution:

This wording is relative to N3936.

1. Change 25.2.10 [mismatch] p3 as indicated:

   > -3- Complexity: At most `min(last1 - first1, last2 - first2)` applications of the corresponding predicate.

### 2406. `negative_binomial_distribution` should reject `p == 1`

Section: 26.5.8.3.4 [rand.dist.bern.negbin] Status: New Submitter: Stephan T. Lavavej Opened: 2014-06-14 Last modified: 2014-06-17

View all issues with New status.

Discussion:

26.5.8.3.4 [rand.dist.bern.negbin] p2 requires "`0 < p <= 1`". Consider what happens when `p == 1`. The discrete probability function specified by p1 involves "`* p^k * (1 - p)^i`". For `p == 1`, this is "`* 1^k * 0^i`", so every integer `i >= 0` is produced with zero probability. (Let's avoid thinking about `0^0`.)

Wikipedia states that `p` must be within `(0, 1)`, exclusive on both sides.

Proposed resolution:

This wording is relative to N3936.

1. Change 26.5.8.3.4 [rand.dist.bern.negbin] p2 as indicated: [Drafting note: This should be read as: Replace the symbol "`≤`" by "`<`" — end drafting note]

   >     explicit negative_binomial_distribution(IntType k = 1, double p = 0.5);

   > > -2- Requires: `0 < p ≤< 1` and `0 < k`.

### 2407. `packaged_task(allocator_arg_t, const Allocator&, F&&)` should neither be constrained nor `explicit`

Section: 30.6.9.1 [futures.task.members] Status: New Submitter: Stephan T. Lavavej Opened: 2014-06-14 Last modified: 2014-06-17

View other active issues in [futures.task.members].

View all other issues in [futures.task.members].

View all issues with New status.

Discussion:

LWG 2097's resolution was slightly too aggressive. It constrained `packaged_task(allocator_arg_t, const Allocator&, F&&)`, but that's unnecessary because `packaged_task` doesn't have any other three-argument constructors. Additionally, it's marked as `explicit` (going back to WP N2798 when `packaged_task` first appeared) which is unnecessary.

Proposed resolution:

This wording is relative to N3936.

1. Change 30.6.9 [futures.task] p2, class template `packaged_task` as indicated:

   >     template <class F>
   >     explicit packaged_task(F&& f);
   >     template <class F, class Allocator>
   >     explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f);

2. Change 30.6.9.1 [futures.task.members] as indicated:

   >     template <class F>
   >     packaged_task(F&& f);
   >     template <class F, class Allocator>
   >     explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f);

   > > […]

   > > -3- Remarks: These constructors The first constructor shall not participate in overload resolution if `decay_t<F>` is the same type as `std::packaged_task<R(ArgTypes...)>`.

### 2408. SFINAE-friendly `common_type/iterator_traits` is missing in C++14

Section: 20.10.7.6 [meta.trans.other], 24.4.1 [iterator.traits] Status: Ready Submitter: Daniel Krügler Opened: 2014-06-19 Last modified: 2014-06-20

View other active issues in [meta.trans.other].

View all other issues in [meta.trans.other].

View all issues with Ready status.

Discussion:

During the Rapperswil meeting the proposal N4041 had been discussed and there seemed to be strong consensus to apply the SFINAE-friendly definitions that currently exist within the fundamentals-ts to the C++ Standard working draft. This issue requests this change to happen.

Proposed resolution:

This wording is relative to N3936.

1. Change 20.10.7.6 [meta.trans.other] p3 as indicated:

   > -3- For the `common_type` trait applied to a parameter pack `T` of types, the member `type` shall be either defined or not present as follows:

   > - If `sizeof...(T)` is zero, there shall be no member `type`.

   > - If `sizeof...(T)` is one, let `T0` denote the sole type comprising `T`. The member typedef `type` shall denote the same type as `decay_t<T0>`.

   > - If `sizeof...(T)` is greater than one, let `T1`, `T2`, and `R`, respectively, denote the first, second, and (pack of) remaining types comprising `T`. [Note: `sizeof...(R)` may be zero. — end note] Finally, let `C` denote the type, if any, of an unevaluated conditional expression (5.16 [expr.cond]) whose first operand is an arbitrary value of type `bool`, whose second operand is an xvalue of type `T1`, and whose third operand is an xvalue of type `T2`. If there is such a type `C`, the member typedef `type` shall denote the same type, if any, as `common_type_t<C,R...>`. Otherwise, there shall be no member `type`.

   > The nested typedef `common_type::type` shall be defined as follows:

   > >     template <class ...T> struct common_type;

   > >     template <class T>
   > >     struct common_type<T> {
   > >       typedef decay_t<T> type;
   > >     };

   > >     template <class T, class U>
   > >     struct common_type<T, U> {
   > >       typedef decay_t<decltype(true ? declval<T>() : declval<U>())> type;
   > >     };

   > >     template <class T, class U, class... V>
   > >     struct common_type<T, U, V...> {
   > >       typedef common_type_t<common_type_t<T, U>, V...> type;
   > >     };

2. Change 24.4.1 [iterator.traits] p2 as indicated:

   > -2- The template `iterator_traits<Iterator>` is defined as shall have the following as publicly accessible members, and have no other members, if and only if `Iterator` has valid (14.8.2 [temp.deduct]) member types `difference_type`, `value_type`, `pointer`, `reference`, and `iterator_category`; otherwise, the template shall have no members:

   > >     namespace std {
   > >       template<class Iterator> struct iterator_traits {
   > >         typedef typename Iterator::difference_type difference_type;
   > >         typedef typename Iterator::value_type value_type;
   > >         typedef typename Iterator::pointer pointer;
   > >         typedef typename Iterator::reference reference;
   > >         typedef typename Iterator::iterator_category iterator_category;
   > >       };
   > >     }

### 2410. [fund.ts] `shared_ptr<array>`'s constructor from `unique_ptr` should be constrained

Section: X [mods.util.smartptr.shared.const] Status: New Submitter: Jeffrey Yasskin Opened: 2014-06-16 Last modified: 2014-07-01

View all issues with New status.

Discussion:

Addresses: fund.ts

The proposed resolution for LWG 2399 doesn't apply cleanly to the Fundamentals TS, but the issue is still present.

Proposed resolution:

This wording is relative to N4023 in regard to fundamental-ts changes.

1. In fundamental-ts, change [mods.util.smartptr.shared.const] p34 as indicated:

   >     template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);

   > > -34- Requires Remarks: This constructor shall not participate in overload resolution unless `Y*` shall be is compatible with `T*`.

   > > -35- Effects: Equivalent to `shared_ptr(r.release(), r.get_deleter())` when `D` is not a reference type, otherwise `shared_ptr(r.release(), ref(r.get_deleter()))`.

   > > -36- Exception safety: If an exception is thrown, the constructor has no effect.

### 2411. `shared_ptr` is only contextually convertible to `bool`

Section: 20.8.2.2 [util.smartptr.shared] Status: New Submitter: Jonathan Wakely Opened: 2014-06-21 Last modified: 2014-07-01

View other active issues in [util.smartptr.shared].

View all other issues in [util.smartptr.shared].

View all issues with New status.

Discussion:

N3920 made this edit, which is correct but unrelated to the support for arrays:

> Change 20.7.2.2 [util.smartptr.shared] p2 as follows:

> > Specializations of `shared_ptr` shall be `CopyConstructible`, `CopyAssignable`, and `LessThanComparable`, allowing their use in standard containers. Specializations of `shared_ptr` shall be contextually convertible to `bool`, allowing their use in boolean expressions and declarations in conditions. […]

That change is actually fixing a defect in the current wording and should be applied directly to the working paper, not just to the Library Fundamentals TS. The declarations of the conversion operator in 20.8.2.2 [util.smartptr.shared] and 20.8.2.2.5 [util.smartptr.shared.obs] are `explicit` which contradicts the "convertible to `bool`" statement. The intention is definitely for `shared_ptr` to only be contextually convertible to `bool`.

Proposed resolution:

This wording is relative to N3936.

1. Change 20.8.2.2 [util.smartptr.shared] p2 as indicated:

   > -2- Specializations of `shared_ptr` shall be `CopyConstructible`, `CopyAssignable`, and `LessThanComparable`, allowing their use in standard containers. Specializations of `shared_ptr` shall be contextually convertible to `bool`, allowing their use in boolean expressions and declarations in conditions. The template parameter `T` of `shared_ptr` may be an incomplete type.

### 2412. `promise::set_value()` and `promise::get_future()` should not race

Section: 30.6.5 [futures.promise], 30.6.9.1 [futures.task.members] Status: New Submitter: Jonathan Wakely Opened: 2014-06-23 Last modified: 2014-07-01

View other active issues in [futures.promise].

View all other issues in [futures.promise].

View all issues with New status.

Discussion:

The following code has a data race according to the standard:

>     std::promise<void> p;
>     std::thread t{ []{
>       p.get_future().wait();
>     }};
>     p.set_value();
>     t.join();

The problem is that both `promise::set_value()` and `promise::get_future()` are non-const member functions which modify the same object, and we only have wording saying that the `set_value()` and `wait()` calls (i.e. calls setting and reading the shared state) are synchronized.

The calls don't actually access the same memory locations, so the standard should allow it. My suggestion is to state that calling `get_future()` does not conflict with calling the various functions that make the shared state ready, but clarify with a note that this does not imply any synchronization or "happens before", only being free from data races.

Proposed resolution:

This wording is relative to N3936.

1. Change 30.6.5 [futures.promise] around p12 as indicated:

   >     future<R> get_future();

   > > -12- Returns: A `future<R>` object with the same shared state as `*this`.

   > > -?- Synchronization: Calls to this function do not conflict (1.10 [intro.multithread]) with calls to `set_value`, `set_exception`, `set_value_at_thread_exit`, or `set_exception_at_thread_exit`. [Note: Such calls need not be synchronized, but implementations must ensure they do not introduce data races. — end note]

   > > -13- Throws: `future_error` if `*this` has no shared state or if `get_future` has already been called on a `promise` with the same shared state as `*this`.

   > > -14- Error conditions: […]

2. Change 30.6.9.1 [futures.task.members] around p13 as indicated:

   >     future<R> get_future();

   > > -13- Returns: A `future<R>` object that shares the same shared state as `*this`.

   > > -?- Synchronization: Calls to this function do not conflict (1.10 [intro.multithread]) with calls to `operator()` or `make_ready_at_thread_exit`. [Note: Such calls need not be synchronized, but implementations must ensure they do not introduce data races. — end note]

   > > -14- Throws: a `future_error` object if an error occurs.

   > > -15- Error conditions: […]

### 2413. `assert` macro is overconstrained

Section: 19.3 [assertions] Status: New Submitter: David Krauss Opened: 2014-06-25 Last modified: 2014-07-01

View other active issues in [assertions].

View all other issues in [assertions].

View all issues with New status.

Discussion:

When `NDEBUG` is defined, `assert` must expand exactly to the token sequence `((void)0)`, with no whitespace (C99 §7.2/1 and also C11 §7.2/1). This is a lost opportunity to pass the condition along to the optimizer.

The user may observe the token sequence using the stringize operator or discriminate it by making a matching `#define` directive. There is little chance of practical code doing such things. It's reasonable to allow any expansion that is a `void` expression with no side effects or semantic requirements, for example, an extension keyword or an attribute-specifier finagled into the context.

Conforming optimizations would still be limited to treating the condition as hint, not a requirement. Nonconformance on this point is quite reasonable though, given user preferences. Anyway, it shouldn't depend on preprocessor quirks.

As for current practice, Darwin OS `<assert.h>` provides a GCC-style compiler hint `__builtin_expect` but only in debug mode. Shouldn't release mode preserve hints?

Daniel:

The corresponding resolution should take care not to conflict with the intention behind LWG 2234.

Proposed resolution:

### 2414. Member function reentrancy should be implementation-defined

Section: 17.6.5.8 [reentrancy] Status: New Submitter: Stephan T. Lavavej Opened: 2014-07-01 Last modified: 2014-07-08

View other active issues in [reentrancy].

View all other issues in [reentrancy].

View all issues with New status.

Discussion:

N3936 17.6.5.8 [reentrancy]/1 talks about "functions", but that doesn't address the scenario of calling different member functions of a single object. Member functions often have to violate and then re-establish invariants. For example, vectors often have "holes" during insertion, and element constructors/destructors/etc. shouldn't be allowed to observe the vector while it's in this invariant-violating state. The [reentrancy] Standardese should be extended to cover member functions, so that implementers can either say that member function reentrancy is universally prohibited, or selectively allowed for very specific scenarios.

(For clarity, this issue has been split off from LWG 2382.)

Proposed resolution:

This wording is relative to N3936.

1. Change 17.6.5.8 [reentrancy] p1 as indicated:

   > -1- Except where explicitly specified in this standard, it is implementation-defined which functions (including different member functions called on a single object) in the Standard C++ library may be recursively reentered.

### 2415. Inconsistency between `unique_ptr` and `shared_ptr`

Section: 20.8.2.2.1 [util.smartptr.shared.const] Status: New Submitter: Jonathan Wakely Opened: 2014-07-03 Last modified: 2014-07-08

View other active issues in [util.smartptr.shared.const].

View all other issues in [util.smartptr.shared.const].

View all issues with New status.

Discussion:

`unique_ptr` guarantees that it will not invoke its deleter if it stores a null pointer, which is useful for deleters that must not be called with a null pointer e.g.

>     unique_ptr<FILE, int(*)(FILE*)> fptr(file, &::fclose);

However, `shared_ptr` does invoke the deleter if it owns a null pointer, which is a silent change in behaviour when transferring ownership from `unique_ptr` to `shared_ptr`. That means the following leads to undefined behaviour:

>     std:shared_ptr<FILE> fp = std::move(fptr);

Peter Dimov's suggested fix is to construct an empty `shared_ptr` from a `unique_ptr` that contains a null pointer.

Proposed resolution:

This wording is relative to N3936.

1. Change 20.8.2.2.1 [util.smartptr.shared.const] p33 as indicated:

   >     template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);

   > > -33- Effects: Equivalent to `shared_ptr()` if `r.get() == nullptr`, otherwise equivalent to `shared_ptr(r.release(), r.get_deleter())` when `D` is not a reference type, otherwise `shared_ptr(r.release(), ref(r.get_deleter()))`.