Skip to content

Commit 3f4ebb0

Browse files
committed
inplace util
1 parent a643422 commit 3f4ebb0

File tree

2 files changed

+60
-9
lines changed

2 files changed

+60
-9
lines changed

include/anyany/anyany.hpp

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,35 @@ struct unreachable_allocator {
11001100
}
11011101
};
11021102

1103+
// it is a tag type for contructing basic_any in place without move similar to std::in_place_t
1104+
// example:
1105+
//
1106+
// my_any foo() {
1107+
// // returned 'my_any' will contain 'some_type'
1108+
// return inplaced([&] { return some_type(args...); })
1109+
// }
1110+
//
1111+
template <typename F>
1112+
struct inplaced {
1113+
ANYANY_NO_UNIQUE_ADDRESS F f;
1114+
1115+
using value_type = decltype(std::declval<F>()());
1116+
1117+
static_assert(std::is_same_v<std::decay_t<value_type>, value_type>);
1118+
1119+
operator value_type() && {
1120+
return std::move(f)();
1121+
}
1122+
#if __cpp_aggregate_paren_init < 201902L
1123+
inplaced() = default;
1124+
inplaced(F foo) noexcept(std::is_nothrow_move_constructible_v<F>) : f(std::move(foo)) {
1125+
}
1126+
#endif
1127+
};
1128+
1129+
template <typename F>
1130+
inplaced(F&&) -> inplaced<std::decay_t<F>>;
1131+
11031132
// dont use it directly, instead use any_with / basic_any_with
11041133
// SooS == Small Object Optimization Size
11051134
// strong exception guarantee for constructors and copy/move assignments
@@ -1292,6 +1321,13 @@ struct basic_any : construct_interface<basic_any<Alloc, SooS, Methods...>, Metho
12921321
return emplace<std::decay_t<T>, std::initializer_list<U>, Args...>(std::move(list),
12931322
std::forward<Args>(args)...);
12941323
}
1324+
1325+
// constructs any with 'f::value_type' in it
1326+
template <typename F>
1327+
basic_any(inplaced<F> f) noexcept(noexcept(f.f())) {
1328+
emplace_in_empty<typename inplaced<F>::value_type>(std::move(f));
1329+
}
1330+
12951331
template <typename T, typename... Args, std::enable_if_t<exist_for<T, Methods...>::value, int> = 0>
12961332
basic_any(std::in_place_type_t<T>,
12971333
Args&&... args) noexcept(std::is_nothrow_constructible_v<std::decay_t<T>, Args&&...> &&
@@ -1601,7 +1637,7 @@ struct any_cast_fn<T, anyany_poly_traits> {
16011637
}
16021638
#if __cpp_exceptions
16031639
template <typename U, std::enable_if_t<is_any<U>::value, int> = 0>
1604-
decltype(auto) operator()(U && any) const {
1640+
decltype(auto) operator()(U&& any) const {
16051641
auto* ptr = (*this)(std::addressof(any));
16061642
if (!ptr)
16071643
throw aa::bad_cast{};
@@ -1620,9 +1656,8 @@ struct any_cast_fn<T, anyany_poly_traits> {
16201656
}
16211657
#else
16221658
template <typename U, std::enable_if_t<is_any<U>::value, int> = 0>
1623-
decltype(auto) operator()(U && any) const {
1624-
static_assert(
1625-
![] {}, "exceptions disabled, use nothrow version");
1659+
decltype(auto) operator()(U&& any) const {
1660+
static_assert(![] {}, "exceptions disabled, use nothrow version");
16261661
}
16271662
#endif
16281663

@@ -1653,8 +1688,7 @@ struct any_cast_fn<T, anyany_poly_traits> {
16531688
std::conditional_t<std::is_rvalue_reference_v<T>, noexport::remove_cvref_t<T>,
16541689
std::conditional_t<std::is_reference_v<T>, T, std::remove_cv_t<T>>>
16551690
operator()(poly_ref<Methods...> p) const {
1656-
static_assert(
1657-
![] {}, "exceptions disabled, use nothrow version");
1691+
static_assert(![] {}, "exceptions disabled, use nothrow version");
16581692
}
16591693
#endif
16601694
#if __cpp_exceptions
@@ -1672,8 +1706,7 @@ struct any_cast_fn<T, anyany_poly_traits> {
16721706
template <typename... Methods>
16731707
std::conditional_t<std::is_reference_v<T>, const X&, std::remove_cv_t<T>> operator()(
16741708
const_poly_ref<Methods...> p) const {
1675-
static_assert(
1676-
![] {}, "exceptions disabled, use nothrow version");
1709+
static_assert(![] {}, "exceptions disabled, use nothrow version");
16771710
}
16781711
#endif
16791712

@@ -1931,7 +1964,7 @@ struct call {};
19311964
struct call<Ret(Args...) CONST NOEXCEPT> { \
19321965
template <typename T> \
19331966
static auto do_invoke(CONST T& self, Args... args) NOEXCEPT \
1934-
->decltype(static_cast<Ret>(self(static_cast<Args&&>(args)...))) { \
1967+
-> decltype(static_cast<Ret>(self(static_cast<Args&&>(args)...))) { \
19351968
return static_cast<Ret>(self(static_cast<Args&&>(args)...)); \
19361969
} \
19371970
using signature_type = Ret(CONST ::aa::erased_self_t&, Args...) NOEXCEPT; \

tests/test_anyany.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,7 +1362,25 @@ TEST(memory_reuse) {
13621362
return error_count;
13631363
}
13641364

1365+
struct inplace_tester {
1366+
int f = 0;
1367+
std::string s = "hello";
1368+
1369+
inplace_tester() = default;
1370+
inplace_tester(inplace_tester&&) = delete;
1371+
void operator=(inplace_tester&&) = delete;
1372+
1373+
bool operator==(const inplace_tester& t) const {
1374+
return t.f == f && t.s == s;
1375+
}
1376+
};
1377+
1378+
static_assert(!std::is_move_constructible_v<inplace_tester>);
1379+
13651380
int main() {
1381+
aa::any_with<aa::type_info, aa::equal_to> some = aa::inplaced([&] { return inplace_tester{}; });
1382+
if (!(aa::any_cast<inplace_tester&>(some) == inplace_tester{}))
1383+
return -1;
13661384
#ifndef _MSC_VER
13671385
static_assert((sizeof(aa::basic_any_with<aa::default_allocator, 0>)) ==
13681386
(sizeof(void*) * 2 + sizeof(size_t)));

0 commit comments

Comments
 (0)