Skip to content

Conversation

@ArtemSarmini
Copy link
Contributor

@ArtemSarmini ArtemSarmini commented Jan 15, 2020

Description

Resolves #19 and resolves #20. I mostly copied standard quotes, unrolled some function calls and _Uglified. Now I wonder if it is possible to merge some code between uses_allocator_construction_args and _Uses_allocator_construct (from xpolymorphic_allocator.h), their purpose is same it seems.

Checklist

Be sure you've read README.md and understand the scope of this repo.

If you're unsure about a box, leave it unchecked. A maintainer will help you.

  • Identifiers in product code changes are properly _Ugly as per
    https://eel.is/c++draft/lex.name#3.1 or there are no product code changes.
  • The STL builds successfully and all tests have passed (must be manually
    verified by an STL maintainer before automated testing is enabled on GitHub,
    leave this unchecked for initial submission).
  • These changes introduce no known ABI breaks (adding members, renaming
    members, adding virtual functions, changing whether a type is an aggregate
    or trivially copyable, etc.).
  • These changes were written from scratch using only this repository,
    the C++ Working Draft (including any cited standards), other WG21 papers
    (excluding reference implementations outside of proposed standard wording),
    and LWG issues as reference material. If they were derived from a project
    that's already listed in NOTICE.txt, that's fine, but please mention it.
    If they were derived from any other project (including Boost and libc++,
    which are not yet listed in NOTICE.txt), you must mention it here,
    so we can determine whether the license is compatible and what else needs
    to be done.

@ArtemSarmini ArtemSarmini requested a review from a team as a code owner January 15, 2020 12:20
Copy link
Contributor

@miscco miscco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor comments

#if _HAS_CXX20
_Uses_allocator_construct(_Ptr, _Scoped_outermost(*this), inner_allocator(), _STD forward<_Types>(_Args)...);
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
_Uses_allocator_construct(_Ptr, _Scoped_outermost(*this), inner_allocator(), _STD forward<_Types>(_Args)...);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I am blind but arent thesetwo lines identical`?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#if part changed, as in standard, in terms of uses_allocator_construction_args

stl/inc/xmemory Outdated
Comment on lines 2074 to 2078
template <class>
struct _Is_pair : false_type {};

template <class _Ty1, class _Ty2>
struct _Is_pair<pair<_Ty1, _Ty2>> : true_type {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are only ever using the value of _Is_pair so a variable template be better as that does not require a class instantiation

Suggested change
template <class>
struct _Is_pair : false_type {};
template <class _Ty1, class _Ty2>
struct _Is_pair<pair<_Ty1, _Ty2>> : true_type {};
// VARIABLE TEMPLATE _Is_pair_v
template <class>
inline constexpr bool _Is_pair_v = false;
template <class _Ty1, class _Ty2>
inline constexpr bool _Is_pair_v<pair<_Ty1, _Ty2>> = false;

stl/inc/xmemory Outdated
auto uses_allocator_construction_args(const _Alloc& _Al, _Types&&... _Args) {
if constexpr (!uses_allocator_v<_Ty, _Alloc>) {
static_assert(is_constructible_v<_Ty, _Types...>,
"uses_allocator_v<_Ty, _Alloc> is false but _Ty is not constructible from _Types...");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally the error message uses the non-ugly names from the standard, as the user should not have to read the implementation to understand the message. Also I would suggest to formulate it differently along the lines of

T must be constructible from Types... if uses_allocator_v<T, Alloc> is false

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm I think it depends on whether we expect a template instantiation stack to be shown to the user. If the compiler is going to add:

with
  [
    _Ugly = sometype
  ]

to the output IMO it's more confusing to use the pretty name.

stl/inc/xmemory Outdated
return _STD forward_as_tuple(_STD forward<_Types>(_Args)...);
} else {
if constexpr (is_constructible_v<_Ty, allocator_arg_t, _Types...>) {
using _Return_type = _STD tuple<allocator_arg_t, const _Alloc&, _Types&&...>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The _STD qualifier is unecessary as tuple is a type and not a function

stl/inc/xmemory Outdated
return _STD forward_as_tuple(_STD forward<_Types>(_Args)..., _Al);
} else {
static_assert(
_Always_false<_Ty>, "uses_allocator_v<_Ty, _Alloc> is true but _Ty is not constructible with _Alloc");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to above, the names should be non ugly.

stl/inc/xmemory Outdated
_STD forward<_Tuple2>(_Tup2)));
}

template <class _Ty, class _Alloc, enable_if_t<_Is_pair<_Ty>::value, int> = 0>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
template <class _Ty, class _Alloc, enable_if_t<_Is_pair<_Ty>::value, int> = 0>
template <class _Ty, class _Alloc, enable_if_t<_Is_pair_v<_Ty>, int> = 0>

stl/inc/xmemory Outdated
uses_allocator_construction_args<typename _Ty::second_type>(_Al));
}

template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_pair<_Ty>::value, int> = 0>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_pair<_Ty>::value, int> = 0>
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_pair_v<_Ty>, int> = 0>

stl/inc/xmemory Outdated
uses_allocator_construction_args<typename _Ty::second_type>(_Al, _STD forward<_Uty2>(_Val2)));
}

template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_pair<_Ty>::value, int> = 0>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_pair<_Ty>::value, int> = 0>
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_pair_v<_Ty>, int> = 0>

stl/inc/xmemory Outdated
uses_allocator_construction_args<typename _Ty::second_type>(_Al, _Pair.second));
}

template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_pair<_Ty>::value, int> = 0>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_pair<_Ty>::value, int> = 0>
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_pair_v<_Ty>, int> = 0>


template <class _Ty, class _Alloc, enable_if_t<_Is_pair<_Ty>::value, int> = 0>
auto uses_allocator_construction_args(const _Alloc& _Al) {
// equivalent to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you not returning whats the equivalent call? This applies to all functions. As I can see it it involves more function calls.

Copy link
Contributor Author

@ArtemSarmini ArtemSarmini Jan 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it good to have less function template instantiations? And no, it involves one less uses_allocator_construction_args and 2 apply calls in all cases

@AdamBucior
Copy link
Contributor

This also requires changes to <yvals_core.h>.

stl/inc/xmemory Outdated
template <class _Ty1, class _Ty2>
inline constexpr bool _Is_pair_v<pair<_Ty1, _Ty2>> = true;

template <class _Ty, class _Alloc, class... _Types, enable_if_t<!_Is_pair_v<_Ty>, int> = 0>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a c++20 feature. Can't we use concepts there instead of SFINAE?

Copy link
Contributor Author

@ArtemSarmini ArtemSarmini Jan 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if it is allowed, in the standard template parameters are plain classes. Plus we'd need 2 concepts, Pair and NotPair. Anyway, I think this sfinae is rather simple, but I'd rewrite it if concepts are faster in terms of compilation speed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to make any concepts we can just use requires keyword.

Copy link
Contributor

@AdamBucior AdamBucior Jan 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moreover the standard uses the word Constraints

Constraints: T is not a specialization of pair.

which evidently suggests the use of concepts.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think concepts are generally preferable in newer code as they are simpler and provide better error messages.
Nevertheless whether you use a concept or SFINAE is your choice.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SFINAE is horrible. Working with it is one of my biggest nightmares.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a c++20 feature. Can't we use concepts there instead of SFINAE?

Sadly not all the frontends we support have concepts yet.

SFINAE is horrible. Working with it is one of my biggest nightmares.

concepts are mostly SFINAE :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair. I'll keep _Is_pair and replace enable_ifs with requires

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly not all the frontends we support have concepts yet.

Yet. Someday they will.

concepts are mostly SFINAE :)

But 100x simpler and easier to debug.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly not all the frontends we support have concepts yet.

So enable_if remains for now?

@ArtemSarmini
Copy link
Contributor Author

ArtemSarmini commented Jan 22, 2020

Sorry, wrong branch

stl/inc/xmemory Outdated
#if _HAS_CXX20

template <class>
struct _Is_pair : false_type {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is _Is_specialization<T, pair>.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't knew this existed, will try

stl/inc/xmemory Outdated
auto uses_allocator_construction_args(const _Alloc& _Al, _Types&&... _Args) {
if constexpr (!uses_allocator_v<_Ty, _Alloc>) {
static_assert(is_constructible_v<_Ty, _Types...>,
"uses_allocator_v<_Ty, _Alloc> is false but _Ty is not constructible from _Types...");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm I think it depends on whether we expect a template instantiation stack to be shown to the user. If the compiler is going to add:

with
  [
    _Ugly = sometype
  ]

to the output IMO it's more confusing to use the pretty name.

stl/inc/xmemory Outdated
template <class _Ty1, class _Ty2>
inline constexpr bool _Is_pair_v<pair<_Ty1, _Ty2>> = true;

template <class _Ty, class _Alloc, class... _Types, enable_if_t<!_Is_pair_v<_Ty>, int> = 0>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a c++20 feature. Can't we use concepts there instead of SFINAE?

Sadly not all the frontends we support have concepts yet.

SFINAE is horrible. Working with it is one of my biggest nightmares.

concepts are mostly SFINAE :)

@StephanTLavavej
Copy link
Member

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@StephanTLavavej StephanTLavavej added the cxx20 C++20 feature label Feb 5, 2020
@CaseyCarter
Copy link
Contributor

Looks like there are some merge conflicts to resolve, and the new functionality needs some test coverage.

@StephanTLavavej
Copy link
Member

Ping - would you be able to add test coverage here? If not, we can take care of getting this PR ready to merge.

Base automatically changed from master to main January 28, 2021 00:35
@StephanTLavavej
Copy link
Member

Thanks for implementing these features - and apologies for not reviewing this earlier. @AdamBucior has picked this up in #1668 with test coverage, so we'll continue with that PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cxx20 C++20 feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

P0591R4 Utility Functions For Uses-Allocator Construction P0475R1 Guaranteed Copy Elision For Piecewise Construction

6 participants