Skip to content

Commit

Permalink
Make new use list initialization if available
Browse files Browse the repository at this point in the history
This enables uses like `new<std::array<int,5>>(1, 2, 3, 4, 5)` which didn't work before (not even with P0960)

See #740

Note: I chose "use list init if available, else fall back to non-list init" instead of "use paren init if available, else fall back to list init" so that we would get consistent results for initializing a `new<std::vector<int>>` with `(10)`, `(10, 20)`, `(10, 20, 30)`, etc. (i.e., no surprise for `(10, 20)`)
  • Loading branch information
hsutter committed Oct 20, 2023
1 parent 8d66d57 commit e6a1cc3
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 3 deletions.
16 changes: 14 additions & 2 deletions include/cpp2util.h
Original file line number Diff line number Diff line change
Expand Up @@ -556,14 +556,26 @@ auto Typeid() -> decltype(auto) {
struct {
template<typename T>
[[nodiscard]] auto cpp2_new(auto&& ...args) const -> std::unique_ptr<T> {
return std::make_unique<T>(CPP2_FORWARD(args)...);
if constexpr (requires { T{CPP2_FORWARD(args)...}; }) {
// This is because apparently make_unique can't deal with list
// initialization of aggregates, even after P0960
return std::unique_ptr<T>( new T{CPP2_FORWARD(args)...} );
}
else {
return std::make_unique<T>(CPP2_FORWARD(args)...);
}
}
} inline unique;

[[maybe_unused]] struct {
template<typename T>
[[nodiscard]] auto cpp2_new(auto&& ...args) const -> std::shared_ptr<T> {
return std::make_shared<T>(CPP2_FORWARD(args)...);
if constexpr (requires { T{CPP2_FORWARD(args)...}; }) {
return unique.cpp2_new<T>(CPP2_FORWARD(args)...);

This comment has been minimized.

Copy link
@JohelEGP

JohelEGP Oct 21, 2023

Contributor

Is it intentional that this call to shared.cpp2_new returns a call to unique.cpp2_new?

This comment has been minimized.

Copy link
@hsutter

hsutter Oct 21, 2023

Author Owner

Yes, though maybe I should write a comment on why -- that's because the workaround to use { } initialization requires calling naked new to allocate the object separately anyway (defeating the make_shared optimization), so to reduce code duplication I just had it invoke the code that already did that in unique.new (which works because you can convert a unique_ptr to a shared_ptr) instead of writing it in both places.

This comment has been minimized.

Copy link
@hsutter

hsutter Oct 21, 2023

Author Owner

I've gone and added more comments about this implementation choice here: acdd7b3

}
else {
return std::make_shared<T>(CPP2_FORWARD(args)...);
}
}
} inline shared;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Microsoft (R) C/C++ Optimizing Compiler Version 19.37.32824 for x86
Microsoft (R) C/C++ Optimizing Compiler Version 19.37.32825 for x86
Copyright (C) Microsoft Corporation. All rights reserved.

0 comments on commit e6a1cc3

Please sign in to comment.