init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
This commit is contained in:
229
Telegram/lib_base/base/unique_any.h
Normal file
229
Telegram/lib_base/base/unique_any.h
Normal file
@@ -0,0 +1,229 @@
|
||||
// This file is part of Desktop App Toolkit,
|
||||
// a set of libraries for developing nice desktop applications.
|
||||
//
|
||||
// For license and copyright information please follow this link:
|
||||
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <any>
|
||||
|
||||
namespace base {
|
||||
namespace details {
|
||||
|
||||
template <typename Value>
|
||||
struct moveable_as_copyable_wrap {
|
||||
moveable_as_copyable_wrap(Value &&other)
|
||||
: value(std::move(other)) {
|
||||
}
|
||||
moveable_as_copyable_wrap &operator=(Value &&other) {
|
||||
value = std::move(other);
|
||||
return *this;
|
||||
}
|
||||
moveable_as_copyable_wrap(moveable_as_copyable_wrap &&other)
|
||||
: value(std::move(other.value)) {
|
||||
}
|
||||
moveable_as_copyable_wrap(
|
||||
const moveable_as_copyable_wrap &other) {
|
||||
Unexpected("Attempt to copy-construct a move-only type.");
|
||||
}
|
||||
moveable_as_copyable_wrap &operator=(
|
||||
moveable_as_copyable_wrap &&other) {
|
||||
value = std::move(other.value);
|
||||
return *this;
|
||||
}
|
||||
moveable_as_copyable_wrap &operator=(
|
||||
const moveable_as_copyable_wrap &other) {
|
||||
Unexpected("Attempt to copy-assign a move-only type.");
|
||||
}
|
||||
|
||||
Value value;
|
||||
|
||||
};
|
||||
|
||||
template <
|
||||
typename Value,
|
||||
typename = std::enable_if_t<
|
||||
std::is_move_constructible_v<std::decay_t<Value>>
|
||||
&& !std::is_lvalue_reference_v<Value>>>
|
||||
auto wrap_moveable_as_copyable(Value &&value) {
|
||||
return moveable_as_copyable_wrap<Value>(std::move(value));
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
|
||||
class unique_any;
|
||||
|
||||
template <typename Value>
|
||||
Value *any_cast(unique_any *value) noexcept;
|
||||
|
||||
template <typename Value>
|
||||
const Value *any_cast(const unique_any *value) noexcept;
|
||||
|
||||
class unique_any final {
|
||||
public:
|
||||
// Construction and destruction [any.cons]
|
||||
constexpr unique_any() noexcept {
|
||||
}
|
||||
|
||||
unique_any(const unique_any &other) = delete;
|
||||
unique_any &operator=(const unique_any &other) = delete;
|
||||
|
||||
unique_any(unique_any &&other) noexcept
|
||||
: _impl(std::move(other._impl)) {
|
||||
}
|
||||
|
||||
unique_any &operator=(unique_any &&other) noexcept {
|
||||
_impl = std::move(other._impl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <
|
||||
typename Value,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<Value>, unique_any>>>
|
||||
unique_any(Value &&other)
|
||||
: unique_any(
|
||||
std::forward<Value>(other),
|
||||
std::is_copy_constructible<std::decay_t<Value>>()) {
|
||||
}
|
||||
|
||||
template <
|
||||
typename Value,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<Value>, unique_any>>>
|
||||
unique_any &operator=(Value &&other) {
|
||||
if constexpr (std::is_copy_constructible_v<std::decay_t<Value>>) {
|
||||
_impl = std::forward<Value>(other);
|
||||
} else if constexpr (std::is_move_constructible_v<std::decay_t<Value>>
|
||||
&& !std::is_lvalue_reference_v<Value>) {
|
||||
_impl = details::wrap_moveable_as_copyable(std::move(other));
|
||||
} else {
|
||||
static_assert(
|
||||
false_t(Value{}),
|
||||
"Bad value for base::unique_any.");
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <
|
||||
typename Value,
|
||||
typename ...Args,
|
||||
typename = std::enable_if_t<
|
||||
std::is_constructible_v<std::decay_t<Value>, Args...>
|
||||
&& std::is_copy_constructible_v<decay_t<Value>>>>
|
||||
std::decay_t<Value> &emplace(Args &&...args) {
|
||||
return _impl.emplace<Value>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void reset() noexcept {
|
||||
_impl.reset();
|
||||
}
|
||||
|
||||
void swap(unique_any &other) noexcept {
|
||||
_impl.swap(other._impl);
|
||||
}
|
||||
|
||||
bool has_value() const noexcept {
|
||||
return _impl.has_value();
|
||||
}
|
||||
|
||||
// Should check if it is a moveable_only wrap first.
|
||||
//const std::type_info &type() const noexcept {
|
||||
// return _impl.type();
|
||||
//}
|
||||
|
||||
private:
|
||||
template <
|
||||
typename Value,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<Value>, unique_any>
|
||||
&& std::is_copy_constructible_v<std::decay_t<Value>>>>
|
||||
unique_any(Value &&other, std::true_type)
|
||||
: _impl(std::forward<Value>(other)) {
|
||||
}
|
||||
|
||||
template <
|
||||
typename Value,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<Value>, unique_any>
|
||||
&& !std::is_copy_constructible_v<std::decay_t<Value>>
|
||||
&& std::is_move_constructible_v<std::decay_t<Value>>
|
||||
&& !std::is_lvalue_reference_v<Value>>>
|
||||
unique_any(Value &&other, std::false_type)
|
||||
: _impl(details::wrap_moveable_as_copyable(std::move(other))) {
|
||||
}
|
||||
|
||||
template <
|
||||
typename Value,
|
||||
typename ...Args>
|
||||
friend unique_any make_any(Args &&...args);
|
||||
|
||||
template <typename Value>
|
||||
friend const Value *any_cast(const unique_any *value) noexcept;
|
||||
|
||||
template <typename Value>
|
||||
friend Value *any_cast(unique_any *value) noexcept;
|
||||
|
||||
std::any _impl;
|
||||
|
||||
};
|
||||
|
||||
inline void swap(unique_any &a, unique_any &b) noexcept {
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
template <
|
||||
typename Value,
|
||||
typename ...Args>
|
||||
inline auto make_any(Args &&...args)
|
||||
-> std::enable_if_t<
|
||||
std::is_copy_constructible_v<std::decay_t<Value>>,
|
||||
unique_any> {
|
||||
return std::make_any<Value>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <
|
||||
typename Value,
|
||||
typename ...Args>
|
||||
inline auto make_any(Args &&...args)
|
||||
-> std::enable_if_t<
|
||||
!std::is_copy_constructible_v<std::decay_t<Value>>
|
||||
&& std::is_move_constructible_v<std::decay_t<Value>>,
|
||||
unique_any> {
|
||||
return Value(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename Value>
|
||||
inline Value *any_cast(unique_any *value) noexcept {
|
||||
if constexpr (std::is_copy_constructible_v<Value>) {
|
||||
return std::any_cast<Value>(&value->_impl);
|
||||
} else if constexpr (std::is_move_constructible_v<Value>) {
|
||||
auto wrap = std::any_cast<
|
||||
details::moveable_as_copyable_wrap<Value>
|
||||
>(&value->_impl);
|
||||
return wrap ? &wrap->value : nullptr;
|
||||
} else {
|
||||
static_assert(
|
||||
false_t(Value{}),
|
||||
"Bad type for base::any_cast.");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Value>
|
||||
inline const Value *any_cast(const unique_any *value) noexcept {
|
||||
if constexpr (std::is_copy_constructible_v<Value>) {
|
||||
return std::any_cast<Value>(&value->_impl);
|
||||
} else if constexpr (std::is_move_constructible_v<Value>) {
|
||||
auto wrap = std::any_cast<
|
||||
details::moveable_as_copyable_wrap<Value>
|
||||
>(&value->_impl);
|
||||
return wrap ? &wrap->value : nullptr;
|
||||
} else {
|
||||
static_assert(
|
||||
false_t(Value{}),
|
||||
"Bad type for base::any_cast.");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
Reference in New Issue
Block a user