This page is a snapshot from the LWG issues list, see theLibrary Active Issues List for more information and the meaning ofC++17 status.
pair andtuple are not correctly implemented foris_constructible with no argsSection: 21.3.6.4[meta.unary.prop]Status:C++17Submitter: Howard HinnantOpened: 2014-02-19Last modified: 2017-07-30
Priority:3
View otheractive issues in [meta.unary.prop].
View all otherissues in [meta.unary.prop].
View all issues withC++17 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 thesestatic_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 specializingis_constructible onpair andtuple 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 forcv-qualified objects ofpair or for references of them during reference-initialization.
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.
Add to 22.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>{};Add to 22.4.12[tuple.special]:
template <class ...T>struct is_constructible<tuple<T...>> : integral_constant<bool,see below>{};-?- The second argument to
integral_constantshall be true if for eachT,is_default_constructible<T>::valueis true.
[2015-05, Lenexa]
STL: I object to this resolution due to British spelling of behavior
JW: we already have other places of this spelling
VV: the easy resolution is to remove the notes
MC: if that's all we want to change: put it in and make the editorial change of removing the note
VV: the other paper doesn't make any of these changes so it would be consistent
JW: this make me want even more the features of having constructors doing the Right Thing- I haven't written up the request to do something like that
VV: so it would be an aggregate reflecting the properties of the constituting types
JW: I should write that up
MC: any objection to move to ready? in favor: 16, opposed: 0, abstain: 1
Proposed resolution:
This wording is relative to N3936.
Change 22.3.2[pairs.pair] around p3 as indicated:
constexpr pair();-4-Effects: Value-initializes first and second.-?-Remarks: This constructor shall not participate in overload resolution unless
-3-Requires:is_default_constructible<first_type>::valueis true andis_default_constructible<second_type>::valueis true.is_default_constructible<first_type>::valueis true andis_default_constructible<second_type>::valueis true. [Note: This behaviour can be implementedby a constructor template with default template arguments —end note].
Change 22.4.4.2[tuple.cnstr] around p4 as indicated:
constexpr tuple();-5-Effects: Value initializes each element.-?-Remarks: This constructor shall not participate in overload resolution unless
-4-Requires:is_default_constructible<Ti>::valueis true for alli.is_default_constructible<Ti>::valueis true for alli. [Note: This behaviour can be implemented by a constructor template with default template arguments —end note].