Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LWG-3158 tuple(allocator_arg_t, const Alloc&) should be conditionally explicit #69

Closed
StephanTLavavej opened this issue Sep 6, 2019 · 4 comments
Labels
fixed Something works now, yay! LWG Library Working Group issue
Milestone

Comments

@StephanTLavavej
Copy link
Member

StephanTLavavej commented Sep 6, 2019

LWG-3158 tuple(allocator_arg_t, const Alloc&) should be conditionally explicit

@StephanTLavavej StephanTLavavej added the LWG Library Working Group issue label Sep 6, 2019
@NathanSWard
Copy link
Contributor

I believe I should be able to implement this if no one else already is!

@StephanTLavavej
Copy link
Member Author

Sounds good! We already have explicit(bool) and SFINAE implementations for the other constructors, so you can follow that pattern. (Someday we hope to be able to use explicit(bool) unconditionally even in C++14 mode, but that is not yet possible.)

@NathanSWard
Copy link
Contributor

NathanSWard commented Oct 18, 2019

@StephanTLavavej Since LWG 3158 states "The expression inside explicit evaluates to true if and only if Ti is not copy-list-initializable from an empty list for at least one i", the current _Tuple_conditional_explicit_v will not correctly check this, correct?
This means I'll need to implement a way to check if all types are copy-list-initializable. Or am I just not correctly understanding what _Tuple_conditional_explicit_v does?

@StephanTLavavej
Copy link
Member Author

Good catch! _Tuple_conditional_explicit_v isn't involved here (it's used for non-zero-argument constructors). Instead, we're currently using _Is_implicitly_default_constructible:

STL/stl/inc/tuple

Lines 259 to 284 in 957fe99

#if _HAS_CONDITIONAL_EXPLICIT
template <class _This2 = _This,
enable_if_t<conjunction_v<is_default_constructible<_This2>, is_default_constructible<_Rest>...>, int> = 0>
constexpr explicit(
!conjunction_v<_Is_implicitly_default_constructible<_This2>, _Is_implicitly_default_constructible<_Rest>...>)
tuple() noexcept(conjunction_v<is_nothrow_default_constructible<_This2>,
is_nothrow_default_constructible<_Rest>...>) // strengthened
: _Mybase(), _Myfirst() {}
#else // ^^^ _HAS_CONDITIONAL_EXPLICIT ^^^ / vvv !_HAS_CONDITIONAL_EXPLICIT vvv
template <class _This2 = _This,
enable_if_t<conjunction_v<is_default_constructible<_This2>, is_default_constructible<_Rest>...,
_Is_implicitly_default_constructible<_This2>, _Is_implicitly_default_constructible<_Rest>...>,
int> = 0>
constexpr tuple() noexcept(conjunction_v<is_nothrow_default_constructible<_This2>,
is_nothrow_default_constructible<_Rest>...>) // strengthened
: _Mybase(), _Myfirst() {}
template <class _This2 = _This,
enable_if_t<conjunction_v<is_default_constructible<_This2>, is_default_constructible<_Rest>...,
negation<conjunction<_Is_implicitly_default_constructible<_This2>,
_Is_implicitly_default_constructible<_Rest>...>>>,
int> = 0>
constexpr explicit tuple() noexcept(conjunction_v<is_nothrow_default_constructible<_This2>,
is_nothrow_default_constructible<_Rest>...>) // strengthened
: _Mybase(), _Myfirst() {}
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^

STL/stl/inc/type_traits

Lines 661 to 672 in 957fe99

// STRUCT TEMPLATE _Is_implicitly_default_constructible
template <class _Ty, class = void>
struct _Is_implicitly_default_constructible : false_type {
// determine whether _Ty can be copy-initialized with {}
};
template <class _Ty>
void _Implicitly_default_construct(const _Ty&);
template <class _Ty>
struct _Is_implicitly_default_constructible<_Ty, void_t<decltype(_Implicitly_default_construct<_Ty>({}))>> : true_type {
};

This checks whether _Implicitly_default_construct<_Ty>({}) is well-formed. So I believe that this part of LWG-3158 is already implemented. If you look at the issue history, this was essentially an editorial cleanup, because "implicitly default-constructible" isn't actually a Phrase of Power in the Standard, and that the (non-normative) Note explaining how to implement this was unchanged (and corresponds to what we're doing in the code).

So, tuple(allocator_arg_t, const Alloc& a) should use the same trait.

This could be an argument for renaming _Is_implicitly_default_constructible to _Is_copy_list_initializable_from_an_empty_list. I would accept such a renaming (it's usually nice to use the same terminology as the Standard), although I won't require it.

@StephanTLavavej StephanTLavavej changed the title LWG 3158 tuple(allocator_arg_t, const Alloc&) should be conditionally explicit LWG-3158 tuple(allocator_arg_t, const Alloc&) should be conditionally explicit Oct 23, 2019
@StephanTLavavej StephanTLavavej added the fixed Something works now, yay! label Oct 23, 2019
@cbezault cbezault added this to the Conformance milestone May 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fixed Something works now, yay! LWG Library Working Group issue
Projects
Status: Done
Development

No branches or pull requests

3 participants