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
34namespace {
35template <typename T>
36using decay_t = typename std::decay<T>::type;
37
38template <bool B, typename T = void>
39using enable_if_t = typename std::enable_if<B, T>::type;
40
41template <bool B, typename T, typename F>
42using conditional_t = typename std::conditional<B, T, F>::type;
43
44template <typename T>
45using remove_cv_t = typename std::remove_cv<T>::type;
46
47template <typename T>
48using remove_reference_t = typename std::remove_reference<T>::type;
49constexpr size_t STACK_STORAGE_SIZE = 2 * sizeof(void*); // NOLINT: global var
50
51template <typename T>
52struct 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
57template <typename T>
58struct 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
63template <typename T>
64struct IsValidCast {
65    static constexpr bool value = std::is_reference<T>::value || std::is_copy_constructible<T>::value;
66};
67} // namespace
68namespace OHOS {
69namespace Media {
70namespace Plugin {
71/**
72 * @brief BadAnyCast exception, which is thrown when error occurs in AnyCast
73 *
74 * @since 1.0
75 * @version 1.0
76 */
77class BadAnyCast : public std::bad_cast {
78public:
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 */
91class Any final {
92public:
93    constexpr Any() noexcept
94    {
95    }
96
97    Any(const Any& other) : functionTable_(other.functionTable_)
98    {
99        if (other.HasValue()) {
100            functionTable_->copy(storage_, other.storage_);
101        }
102    }
103
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>
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>
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>
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
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>
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>
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     */
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     */
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     */
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     */
261    const std::type_info& Type() const noexcept
262    {
263        if (!HasValue()) {
264            return typeid(void);
265        }
266        return functionTable_->type();
267    }
268#else
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
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
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
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
305private:
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
338        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
349        static void Destroy(Storage& storage) noexcept
350        {
351            reinterpret_cast<T*>(storage.trivialStack_.data())->~T();
352        }
353
354        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
360        static void Move(Storage& dest, Storage& source) noexcept
361        {
362            Copy(dest, source);
363            source.trivialStack_.fill(0);
364        }
365
366        static const void* GetConstPtr(const Storage& storage) noexcept
367        {
368            return reinterpret_cast<const void*>(storage.trivialStack_.data());
369        }
370
371        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
380        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
391        static void Destroy(Storage& storage) noexcept
392        {
393            reinterpret_cast<T*>(GetPtr(storage))->~T(); // NOLINT: cast
394        }
395
396        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
402        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
409        static const void* GetConstPtr(const Storage& storage) noexcept
410        {
411            return reinterpret_cast<const void*>(&storage.nonTrivialStack_);
412        }
413
414        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
423        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
434        static void Destroy(Storage& storage) noexcept
435        {
436            delete reinterpret_cast<T*>(storage.heap_); // NOLINT: cast
437            storage.heap_ = nullptr;
438        }
439        static void Copy(Storage& dest, const Storage& source) noexcept
440        {
441            dest.heap_ = new T(*reinterpret_cast<T*>(source.heap_)); // NOLINT: cast
442        }
443        static void Move(Storage& dest, Storage& source) noexcept
444        {
445            dest.heap_ = source.heap_;
446            source.heap_ = nullptr;
447        }
448        static const void* GetConstPtr(const Storage& storage) noexcept
449        {
450            return storage.heap_;
451        }
452        static void* GetPtr(Storage& storage) noexcept
453        {
454            return storage.heap_;
455        }
456    };
457
458    template <typename ValueType>
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
482    bool IsFunctionTableValid() const noexcept
483    {
484        return functionTable_ != nullptr;
485    }
486
487    template <typename DecayedValueType, typename... 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
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>
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
552private:
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 */
565template <typename ValueType>
566const 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  */
584template <typename ValueType>
585bool 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 */
615template <typename ValueType>
616ValueType* 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 */
635template <typename ValueType>
636ValueType 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 */
660template <typename ValueType>
661ValueType 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 */
685template <typename ValueType>
686ValueType 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 */
708template <typename T, typename... Args>
709Any 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 */
726template <typename T, typename U, typename... Args>
727Any 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
737namespace std {
738inline 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