1 /*
2 * Copyright (c) 2021-2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef HISTREAMER_PLUGIN_COMMON_ANY_H
17 #define HISTREAMER_PLUGIN_COMMON_ANY_H
18
19 #if defined(__clang__) || defined(__GNUC__)
20 #define CPP_STANDARD __cplusplus
21 #elif defined(_MSC_VER)
22 #define CPP_STANDARD _MSVC_LANG
23 #endif
24
25 #if CPP_STANDARD >= 201103L
26
27 #include <array>
28 #include <cstring>
29 #include <string_view>
30 #include <type_traits>
31 #include "plugin/common/type_cast_ext.h"
32 #include "securec.h"
33
34 namespace {
35 template <typename T>
36 using decay_t = typename std::decay<T>::type;
37
38 template <bool B, typename T = void>
39 using enable_if_t = typename std::enable_if<B, T>::type;
40
41 template <bool B, typename T, typename F>
42 using conditional_t = typename std::conditional<B, T, F>::type;
43
44 template <typename T>
45 using remove_cv_t = typename std::remove_cv<T>::type;
46
47 template <typename T>
48 using remove_reference_t = typename std::remove_reference<T>::type;
49 constexpr size_t STACK_STORAGE_SIZE = 2 * sizeof(void*); // NOLINT: global var
50
51 template <typename T>
52 struct IsTrivialStackStorable {
53 static constexpr bool value =
54 alignof(T) <= alignof(max_align_t) && std::is_trivially_copyable<T>::value && sizeof(T) <= STACK_STORAGE_SIZE;
55 };
56
57 template <typename T>
58 struct IsStackStorable {
59 static constexpr bool value = alignof(T) <= alignof(max_align_t) && std::is_nothrow_move_constructible<T>::value &&
60 sizeof(T) <= STACK_STORAGE_SIZE;
61 };
62
63 template <typename T>
64 struct IsValidCast {
65 static constexpr bool value = std::is_reference<T>::value || std::is_copy_constructible<T>::value;
66 };
67 } // namespace
68 namespace OHOS {
69 namespace Media {
70 namespace Plugin {
71 /**
72 * @brief BadAnyCast exception, which is thrown when error occurs in AnyCast
73 *
74 * @since 1.0
75 * @version 1.0
76 */
77 class BadAnyCast : public std::bad_cast {
78 public:
what()79 const char* what() const noexcept override
80 {
81 return "bad any cast";
82 }
83 };
84
85 /**
86 * @brief This class describes a type-safe container for arbitrary type values which are copy constructible.
87 *
88 * @since 1.0
89 * @version 1.0
90 */
91 class Any final {
92 public:
Any()93 constexpr Any() noexcept
94 {
95 }
96
Any(const Any & other)97 Any(const Any& other) : functionTable_(other.functionTable_)
98 {
99 if (other.HasValue()) {
100 functionTable_->copy(storage_, other.storage_);
101 }
102 }
103
Any(Any && other)104 Any(Any&& other) noexcept : functionTable_(other.functionTable_)
105 {
106 if (other.HasValue()) {
107 functionTable_->move(storage_, other.storage_);
108 other.functionTable_ = nullptr;
109 }
110 }
111
112 /**
113 * constructor from right reference value with type of ValueType.
114 *
115 * @tparam Type ValueType is not the same as Any itself. The decay type of ValueType must be copy constructible.
116 * @param value content
117 */
118 template <typename ValueType, enable_if_t<!std::is_same<decay_t<ValueType>, Any>::value &&
119 std::is_copy_constructible<decay_t<ValueType>>::value,
120 bool> = true>
Any(ValueType && value)121 Any(ValueType&& value) // NOLINT: explicit
122 {
123 DoEmplace<decay_t<ValueType>>(std::forward<ValueType>(value));
124 }
125
126 Any& operator=(const Any& other)
127 {
128 *this = Any(other);
129 return *this;
130 }
131
132 Any& operator=(Any&& other) noexcept
133 {
134 Reset();
135 MoveFrom(std::forward<Any>(other));
136 return *this;
137 }
138
139 /**
140 * Assigns contents to Any.
141 *
142 * @tparam ValueType Type ValueType is not the same as Any itself. The decay type of ValueType must be copy
143 * constructible.
144 * @param value content
145 * @return
146 */
147 template <typename ValueType, enable_if_t<!std::is_same<decay_t<ValueType>, Any>::value &&
148 std::is_copy_constructible<decay_t<ValueType>>::value,
149 bool> = true>
150 Any& operator=(ValueType&& value)
151 {
152 *this = Any(std::forward<ValueType>(value));
153 return *this;
154 }
155
156 template<typename T>
GetTypeName()157 static constexpr std::string_view GetTypeName() noexcept
158 {
159 const char* charInfo = __PRETTY_FUNCTION__ ;
160 std::string_view stringInfo = charInfo;
161 uint32_t beginIndex = stringInfo.find_first_of('=') + 2; // 2 表示右移两位
162 uint32_t endIndex = stringInfo.find_first_of(']');
163 std::string_view typeName(charInfo + beginIndex, endIndex - beginIndex + 1);
164 return typeName;
165 }
166
167 template<typename T>
IsSameTypeWith(const Any & other)168 static bool IsSameTypeWith(const Any& other) noexcept
169 {
170 #ifndef HST_ANY_WITH_NO_RTTI
171 return other.SameTypeWith(typeid(T));
172 #else
173 return other.SameTypeWith(Any::GetTypeName<T>());
174 #endif
175 }
176
~Any()177 ~Any()
178 {
179 Reset();
180 }
181
182 /**
183 * Emplace one content with type of ValueType into object. The content is constructed by args.
184 *
185 * @tparam ValueType The decay type of ValueType must be constructible from args and copy constructible.
186 * @tparam Args args type
187 * @param args args
188 * @return content with type of decay ValueType
189 */
190 template <typename ValueType, typename... Args,
191 enable_if_t<std::is_constructible<decay_t<ValueType>, Args...>::value &&
192 std::is_copy_constructible<decay_t<ValueType>>::value,
193 bool> = true>
Emplace(Args &&...args)194 decay_t<ValueType>& Emplace(Args&&... args)
195 {
196 Reset();
197 return DoEmplace<decay_t<ValueType>>(std::forward<Args>(args)...);
198 }
199
200 /**
201 * Emplace one content with type of ValueType into object. The content is constructed by il and args.
202 *
203 * @tparam ValueType type of conetent. The decay type of ValueType must be constructible from il and args and copy
204 * constructible
205 * @tparam U type of initializer list.
206 * @tparam Args type of other args
207 * @param il initializer list
208 * @param args args
209 * @return content with type of decay ValueType
210 */
211 template <typename ValueType, typename U, typename... Args,
212 enable_if_t<std::is_constructible<decay_t<ValueType>, std::initializer_list<U>&, Args...>::value &&
213 std::is_copy_constructible<decay_t<ValueType>>::value,
214 bool> = true>
Emplace(std::initializer_list<U> il,Args &&...args)215 decay_t<ValueType>& Emplace(std::initializer_list<U> il, Args&&... args)
216 {
217 Reset();
218 return DoEmplace<decay_t<ValueType>>(il, std::forward<Args>(args)...);
219 }
220
221 /**
222 * Destroy the inner content if exists.
223 */
Reset()224 void Reset() noexcept
225 {
226 if (HasValue()) {
227 functionTable_->destroy(storage_);
228 storage_.trivialStack_.fill(0);
229 }
230 functionTable_ = nullptr;
231 }
232
233 /**
234 * swap contents of two any objects
235 *
236 * @param other object to swap with
237 */
Swap(Any & other)238 void Swap(Any& other) noexcept
239 {
240 Any tmp(std::move(*this));
241 *this = std::move(other);
242 other = std::move(tmp);
243 }
244
245 /**
246 * Checks whether the object has one content.
247 *
248 * @return true if object has one content, otherwise false.
249 */
HasValue()250 bool HasValue() const noexcept
251 {
252 return IsFunctionTableValid();
253 }
254
255 #ifndef HST_ANY_WITH_NO_RTTI
256 /**
257 * Get tye type_info of object
258 *
259 * @return type info of object
260 */
Type()261 const std::type_info& Type() const noexcept
262 {
263 if (!HasValue()) {
264 return typeid(void);
265 }
266 return functionTable_->type();
267 }
268 #else
TypeName()269 std::string_view TypeName() const noexcept
270 {
271 if (!HasValue()) {
272 return "empty"; // no value
273 }
274 return functionTable_->type_name();
275 }
276 #endif
277
278 #ifndef HST_ANY_WITH_NO_RTTI
SameTypeWith(const std::type_info & otherInfo)279 bool SameTypeWith(const std::type_info& otherInfo) const noexcept
280 {
281 if (functionTable_ == nullptr) {
282 return false;
283 }
284 return IsSameType(functionTable_->type(), otherInfo);
285 }
286 #else
SameTypeWith(std::string_view otherTypeName)287 bool SameTypeWith(std::string_view otherTypeName) const noexcept
288 {
289 if (functionTable_ == nullptr) {
290 return false;
291 }
292 return IsSameType(functionTable_->type_name(), otherTypeName);
293 }
294 #endif
295
SameTypeWith(const Any & other)296 bool SameTypeWith(const Any& other) const noexcept
297 {
298 #ifndef HST_ANY_WITH_NO_RTTI
299 return IsSameType(functionTable_->type(), other.Type());
300 #else
301 return IsSameType(functionTable_->type_name(), other.TypeName());
302 #endif
303 }
304
305 private:
306 template <typename T>
307 friend const T* AnyCast(const Any* operand) noexcept;
308 template <typename T>
309 friend T* AnyCast(Any* operand) noexcept;
310 template <typename T>
311 friend bool AnyCast(const Any* operand, T& value) noexcept;
312
313 union Storage {
314 using Stack = std::aligned_storage<STACK_STORAGE_SIZE, std::alignment_of<void*>::value>::type;
315 using Heap = void*;
316
317 std::array<uint8_t, STACK_STORAGE_SIZE> trivialStack_;
318 Stack nonTrivialStack_;
319 Heap heap_;
320 };
321
322 struct FunctionTable {
323 #ifndef HST_ANY_WITH_NO_RTTI
324 const std::type_info& (*type)() noexcept;
325 #else
326 std::string_view (*type_name)() noexcept;
327 #endif
328 void (*destroy)(Storage&) noexcept;
329 void (*copy)(Storage&, const Storage&) noexcept;
330 void (*move)(Storage&, Storage&) noexcept;
331 void* (*getPtr)(Storage&) noexcept;
332 const void* (*getConstPtr)(const Storage&) noexcept;
333 };
334
335 template <typename T>
336 struct TrivialStackFunctionTable {
337 #ifndef HST_ANY_WITH_NO_RTTI
TypeTrivialStackFunctionTable338 static const std::type_info& Type() noexcept
339 {
340 return typeid(T);
341 }
342 #else
343 static std::string_view TypeName() noexcept
344 {
345 return GetTypeName<T>();
346 }
347 #endif
348
DestroyTrivialStackFunctionTable349 static void Destroy(Storage& storage) noexcept
350 {
351 reinterpret_cast<T*>(storage.trivialStack_.data())->~T();
352 }
353
CopyTrivialStackFunctionTable354 static void Copy(Storage& dest, const Storage& source) noexcept
355 {
356 // memcpy_s will always success in this function
357 (void)memcpy_s(GetPtr(dest), sizeof(Storage), GetConstPtr(source), sizeof(Storage));
358 }
359
MoveTrivialStackFunctionTable360 static void Move(Storage& dest, Storage& source) noexcept
361 {
362 Copy(dest, source);
363 source.trivialStack_.fill(0);
364 }
365
GetConstPtrTrivialStackFunctionTable366 static const void* GetConstPtr(const Storage& storage) noexcept
367 {
368 return reinterpret_cast<const void*>(storage.trivialStack_.data());
369 }
370
GetPtrTrivialStackFunctionTable371 static void* GetPtr(Storage& storage) noexcept
372 {
373 return reinterpret_cast<void*>(storage.trivialStack_.data());
374 }
375 };
376
377 template <typename T>
378 struct StackFunctionTable {
379 #ifndef HST_ANY_WITH_NO_RTTI
TypeStackFunctionTable380 static const std::type_info& Type() noexcept
381 {
382 return typeid(T);
383 }
384 #else
385 static std::string_view TypeName() noexcept
386 {
387 return GetTypeName<T>();
388 }
389 #endif
390
DestroyStackFunctionTable391 static void Destroy(Storage& storage) noexcept
392 {
393 reinterpret_cast<T*>(GetPtr(storage))->~T(); // NOLINT: cast
394 }
395
CopyStackFunctionTable396 static void Copy(Storage& dest, const Storage& source) noexcept
397 {
398 // NOLINTNEXTLINE: reinterpret_cast
399 new (reinterpret_cast<T*>(GetPtr(dest))) T(*reinterpret_cast<const T*>(GetConstPtr(source)));
400 }
401
MoveStackFunctionTable402 static void Move(Storage& dest, Storage& source) noexcept
403 {
404 // NOLINTNEXTLINE: reinterpret_cast
405 new (reinterpret_cast<T*>(GetPtr(dest))) T(std::move(*reinterpret_cast<T*>(GetPtr(source))));
406 Destroy(source);
407 }
408
GetConstPtrStackFunctionTable409 static const void* GetConstPtr(const Storage& storage) noexcept
410 {
411 return reinterpret_cast<const void*>(&storage.nonTrivialStack_);
412 }
413
GetPtrStackFunctionTable414 static void* GetPtr(Storage& storage) noexcept
415 {
416 return reinterpret_cast<void*>(&storage.nonTrivialStack_);
417 }
418 };
419
420 template <typename T>
421 struct HeapFunctionTable {
422 #ifndef HST_ANY_WITH_NO_RTTI
TypeHeapFunctionTable423 static const std::type_info& Type() noexcept
424 {
425 return typeid(T);
426 }
427 #else
428 static std::string_view TypeName() noexcept
429 {
430 return GetTypeName<T>();
431 }
432 #endif
433
DestroyHeapFunctionTable434 static void Destroy(Storage& storage) noexcept
435 {
436 delete reinterpret_cast<T*>(storage.heap_); // NOLINT: cast
437 storage.heap_ = nullptr;
438 }
CopyHeapFunctionTable439 static void Copy(Storage& dest, const Storage& source) noexcept
440 {
441 dest.heap_ = new T(*reinterpret_cast<T*>(source.heap_)); // NOLINT: cast
442 }
MoveHeapFunctionTable443 static void Move(Storage& dest, Storage& source) noexcept
444 {
445 dest.heap_ = source.heap_;
446 source.heap_ = nullptr;
447 }
GetConstPtrHeapFunctionTable448 static const void* GetConstPtr(const Storage& storage) noexcept
449 {
450 return storage.heap_;
451 }
GetPtrHeapFunctionTable452 static void* GetPtr(Storage& storage) noexcept
453 {
454 return storage.heap_;
455 }
456 };
457
458 template <typename ValueType>
GetFunctionTable()459 static FunctionTable* GetFunctionTable()
460 {
461 using DecayedValueType = decay_t<ValueType>;
462 using DetailFunctionTable =
463 conditional_t<IsTrivialStackStorable<DecayedValueType>::value,
464 TrivialStackFunctionTable<DecayedValueType>,
465 conditional_t<IsStackStorable<DecayedValueType>::value,
466 StackFunctionTable<DecayedValueType>, HeapFunctionTable<DecayedValueType>>>;
467 static FunctionTable table = {
468 #ifndef HST_ANY_WITH_NO_RTTI
469 .type = DetailFunctionTable::Type,
470 #else
471 .type_name = DetailFunctionTable::TypeName,
472 #endif
473 .destroy = DetailFunctionTable::Destroy,
474 .copy = DetailFunctionTable::Copy,
475 .move = DetailFunctionTable::Move,
476 .getPtr = DetailFunctionTable::GetPtr,
477 .getConstPtr = DetailFunctionTable::GetConstPtr,
478 };
479 return &table;
480 }
481
IsFunctionTableValid()482 bool IsFunctionTableValid() const noexcept
483 {
484 return functionTable_ != nullptr;
485 }
486
487 template <typename DecayedValueType, typename... Args>
DoEmplace(Args &&...args)488 DecayedValueType& DoEmplace(Args&&... args)
489 {
490 functionTable_ = GetFunctionTable<DecayedValueType>();
491 DecayedValueType* ptr = nullptr;
492 if (IsTrivialStackStorable<DecayedValueType>::value || IsStackStorable<DecayedValueType>::value) {
493 ptr = reinterpret_cast<DecayedValueType*>(functionTable_->getPtr(storage_));
494 new (ptr) DecayedValueType(std::forward<Args>(args)...);
495 } else {
496 storage_.heap_ = new DecayedValueType(std::forward<Args>(args)...);
497 ptr = reinterpret_cast<DecayedValueType*>(storage_.heap_);
498 }
499 return *ptr;
500 }
501
MoveFrom(Any && other)502 void MoveFrom(Any&& other) noexcept
503 {
504 if (other.HasValue()) {
505 functionTable_ = other.functionTable_;
506 functionTable_->move(storage_, other.storage_);
507 other.Reset();
508 }
509 }
510
511 template <typename ValueType>
Cast()512 ValueType* Cast() noexcept
513 {
514 using DecayedValueType = decay_t<ValueType>;
515 if (!IsFunctionTableValid()) {
516 return nullptr;
517 }
518 #ifndef HST_ANY_WITH_NO_RTTI
519 if (!SameTypeWith(typeid(DecayedValueType))) {
520 #else
521 if (!SameTypeWith(Any::GetTypeName<DecayedValueType>())) {
522 #endif
523 return nullptr;
524 }
525 return IsTrivialStackStorable<DecayedValueType>::value
526 ? reinterpret_cast<DecayedValueType*>(storage_.trivialStack_.data())
527 : (IsStackStorable<DecayedValueType>::value
528 ? reinterpret_cast<DecayedValueType*>(&storage_.nonTrivialStack_)
529 : reinterpret_cast<DecayedValueType*>(storage_.heap_));
530 }
531 template <typename ValueType>
532 const ValueType* Cast() const noexcept
533 {
534 using DecayedValueType = decay_t<ValueType>;
535 if (!IsFunctionTableValid()) {
536 return nullptr;
537 }
538 #ifndef HST_ANY_WITH_NO_RTTI
539 if (!SameTypeWith(typeid(DecayedValueType))) {
540 #else
541 if (!SameTypeWith(Any::GetTypeName<DecayedValueType>())) {
542 #endif
543 return nullptr;
544 }
545 return IsTrivialStackStorable<DecayedValueType>::value
546 ? reinterpret_cast<const DecayedValueType*>(storage_.trivialStack_.data())
547 : (IsStackStorable<DecayedValueType>::value
548 ? reinterpret_cast<const DecayedValueType*>(&storage_.nonTrivialStack_)
549 : reinterpret_cast<const DecayedValueType*>(storage_.heap_));
550 }
551
552 private:
553 Storage storage_ {};
554 FunctionTable* functionTable_ {nullptr};
555 };
556
557 /**
558 * cast one Any pointer into ValueType pointer
559 *
560 * @tparam ValueType target value type
561 * @param operand any object
562 * @return nullptr if type mismatch, operand is nullptr, or valueType is function/array. Otherwise, a pointer to the
563 * const value contained by operand.
564 */
565 template <typename ValueType>
566 const ValueType* AnyCast(const Any* operand) noexcept
567 {
568 static_assert(!std::is_void<ValueType>::value, "ValueType of any_cast must not be void");
569 if (std::is_function<ValueType>::value || std::is_array<ValueType>::value || operand == nullptr) {
570 return nullptr;
571 }
572 return operand->Cast<ValueType>();
573 }
574
575 /**
576 * cast one Any pointer into ValueType object
577 *
578 * @tparam ValueType target value type
579 * @param operand any object
580 * @param value ValueType
581 * @return false if type mismatch, operand is nullptr, or valueType is function/array. Otherwise, true to the
582 * value contained by operand.
583 */
584 template <typename ValueType>
585 bool AnyCast(const Any* operand, ValueType& value) noexcept
586 {
587 static_assert(!std::is_void<ValueType>::value, "ValueType of any_cast must not be void");
588 if (std::is_function<ValueType>::value || std::is_array<ValueType>::value || operand == nullptr) {
589 return false;
590 }
591 #ifndef HST_ANY_WITH_NO_RTTI
592 if (!operand->SameTypeWith(typeid(ValueType))) {
593 #else
594 if (!operand->SameTypeWith(Any::GetTypeName<ValueType>())) {
595 #endif
596 return false;
597 } else {
598 auto casted_value = operand->Cast<ValueType>();
599 if (casted_value != nullptr) {
600 value = *casted_value;
601 return true;
602 }
603 return false;
604 }
605 }
606
607 /**
608 * cast one Any pointer into ValueType pointer
609 *
610 * @tparam ValueType target value type
611 * @param operand any object
612 * @return nullptr if type mismatch, operand is nullptr, or valueType is function/array. Otherwise, a pointer to the
613 * value contained by operand.
614 */
615 template <typename ValueType>
616 ValueType* AnyCast(Any* operand) noexcept
617 {
618 static_assert(!std::is_void<ValueType>::value, "ValueType of any_cast must not be void");
619 if (std::is_function<ValueType>::value || std::is_array<ValueType>::value || operand == nullptr) {
620 return nullptr;
621 }
622 return operand->Cast<ValueType>();
623 }
624
625 /**
626 * cast one Any object into ValueType object
627 *
628 * @tparam ValueType target value type. It must match both conditions:
629 * 1. ValueType must be reference or constructible
630 * 2. Let U be remove_cv_t<remove_reference_t<ValueType>>, then std::is_constructible<ValueType, const U&> must be true
631 * @param operand any object
632 * @return throws BadAnyCast exception if type mismatch, operand is nullptr, or valueType is function/array. Otherwise,
633 * one object of ValueType contained in Any.
634 */
635 template <typename ValueType>
636 ValueType AnyCast(const Any& other)
637 {
638 using U = remove_cv_t<remove_reference_t<ValueType>>;
639 static_assert(IsValidCast<ValueType>::value, "template argument must be a reference or has copy constructors");
640 static_assert(std::is_constructible<ValueType, const U&>::value,
641 "any_cast<ValueType>(const any&) requires ValueType constructable from const "
642 "remove_cv_t<remove_reference_t<ValueType>>&");
643 auto ptr = AnyCast<U>(&other);
644 if (ptr == nullptr) {
645 throw BadAnyCast();
646 }
647 return static_cast<ValueType>(*ptr);
648 }
649
650 /**
651 * cast one Any object into ValueType object
652 *
653 * @tparam ValueType target value type. It must match both conditions:
654 * 1. ValueType must be reference or constructible
655 * 2. Let U be remove_cv_t<remove_reference_t<ValueType>>, then std::is_constructible<ValueType, U&> must be true
656 * @param operand any object
657 * @return throws BadAnyCast exception if type mismatch, operand is nullptr, or valueType is function/array. Otherwise,
658 * one object of ValueType contained in Any.
659 */
660 template <typename ValueType>
661 ValueType AnyCast(Any& other)
662 {
663 using U = remove_cv_t<remove_reference_t<ValueType>>;
664 static_assert(IsValidCast<ValueType>::value, "template argument must be a reference or has copy constructors");
665 static_assert(std::is_constructible<ValueType, U&>::value,
666 "any_cast<ValueType>(const any&) requires ValueType constructable from "
667 "remove_cv_t<remove_reference_t<ValueType>>&");
668 auto ptr = AnyCast<U>(&other);
669 if (ptr == nullptr) {
670 throw BadAnyCast();
671 }
672 return static_cast<ValueType>(*ptr);
673 }
674
675 /**
676 * cast one Any object into ValueType object
677 *
678 * @tparam ValueType target value type. It must match both conditions:
679 * 1. ValueType must be reference or constructible
680 * 2. Let U be remove_cv_t<remove_reference_t<ValueType>>, then std::is_constructible<ValueType, U> must be true
681 * @param operand any object
682 * @return throws BadAnyCast exception if type mismatch, operand is nullptr, or valueType is function/array. Otherwise,
683 * one object of ValueType contained in Any.
684 */
685 template <typename ValueType>
686 ValueType AnyCast(Any&& other)
687 {
688 using U = remove_cv_t<remove_reference_t<ValueType>>;
689 static_assert(IsValidCast<ValueType>::value, "template argument must be a reference or has copy constructors");
690 static_assert(std::is_constructible<ValueType, U>::value,
691 "any_cast<ValueType>(const any&) requires ValueType constructable from "
692 "remove_cv_t<remove_reference_t<ValueType>>");
693 auto ptr = AnyCast<U>(&other);
694 if (ptr == nullptr) {
695 throw BadAnyCast();
696 }
697 return static_cast<ValueType>(std::move(*ptr));
698 }
699
700 /**
701 * Constructs Any object, whose content is constructed by args. The content type is T.
702 *
703 * @tparam T type of Any's content
704 * @tparam Args type of args
705 * @param args args used to construct the content
706 * @return Any object
707 */
708 template <typename T, typename... Args>
709 Any MakeAny(Args&&... args)
710 {
711 Any tmp;
712 tmp.Emplace<T, Args...>(std::forward<Args>(args)...);
713 return tmp;
714 }
715
716 /**
717 * Constructs Any object, whose content is constructed by il and args. The content type is T.
718 *
719 * @tparam T type of Any's content
720 * @tparam U type of initializer list
721 * @tparam Args type of args
722 * @param il initializer list
723 * @param args args
724 * @return Any object
725 */
726 template <typename T, typename U, typename... Args>
727 Any MakeAny(std::initializer_list<U> il, Args&&... args)
728 {
729 Any tmp;
730 tmp.Emplace<T, U, Args...>(il, std::forward<Args>(args)...);
731 return tmp;
732 }
733 } // namespace Plugin
734 } // namespace Media
735 } // namespace OHOS
736 #endif
737 namespace std {
swap(OHOS::Media::Plugin::Any & lhs,OHOS::Media::Plugin::Any & rhs)738 inline void swap(OHOS::Media::Plugin::Any& lhs, OHOS::Media::Plugin::Any& rhs) noexcept
739 {
740 lhs.Swap(rhs);
741 }
742 } // namespace std
743 #endif // HISTREAMER_PLUGIN_COMMON_ANY_H
744