AData.h revision 85042380bf7ee3a43eb4cccacdaadfbbafc1522f
1e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/*
2e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Copyright (C) 2016 The Android Open Source Project
3e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
4e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Licensed under the Apache License, Version 2.0 (the "License");
5e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * you may not use this file except in compliance with the License.
6e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * You may obtain a copy of the License at
7e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
8e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *      http://www.apache.org/licenses/LICENSE-2.0
9e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
10e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Unless required by applicable law or agreed to in writing, software
11e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * distributed under the License is distributed on an "AS IS" BASIS,
12e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * See the License for the specific language governing permissions and
14e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * limitations under the License.
15e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
16e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
17e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#ifndef STAGEFRIGHT_FOUNDATION_A_DATA_H_
18e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#define STAGEFRIGHT_FOUNDATION_A_DATA_H_
19e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
20e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#include <memory> // for std::shared_ptr, weak_ptr and unique_ptr
21e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#include <type_traits> // for std::aligned_union
22e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
23e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#include <utils/StrongPointer.h> // for android::sp and wp
24e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
25e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#include <media/stagefright/foundation/TypeTraits.h>
26e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#include <media/stagefright/foundation/Flagged.h>
27e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
2885042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnar#undef HIDE
2985042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnar#define HIDE __attribute__((visibility("hidden")))
3085042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnar
31e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarnamespace android {
32e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
33e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
34e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData is a flexible union type that supports non-POD members. It supports arbitrary types as long
35e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * as they are either moveable or copyable.
36e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
37e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Internally, AData is using AUnion - a structure providing the union support. AUnion should not
38e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * be used by generic code as it is very unsafe - it opens type aliasing errors where an object of
39e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * one type can be easily accessed as an object of another type. AData prevents this.
40e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
41e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData allows a custom type flagger to be used for future extensions (e.g. allowing automatic
42e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * type conversion). A strict and a relaxed flagger are provided as internal types.
43e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
44e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Use as follows:
45e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
46e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<int, float>::Basic data; // strict type support
47e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * int i = 1;
48e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * float f = 7.0f;
49e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
50e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * data.set(5);
51e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_TRUE(data.find(&i));
52e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_FALSE(data.find(&f));
53e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_EQ(i, 5);
54e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
55e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * data.set(6.0f);
56e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_FALSE(data.find(&i));
57e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_TRUE(data.find(&f));
58e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_EQ(f, 6.0f);
59e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
60e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<int, sp<RefBase>>::RelaxedBasic objdata; // relaxed type support
61e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * sp<ABuffer> buf = new ABuffer(16), buf2;
62e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * sp<RefBase> obj;
63e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
64e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * objdata.set(buf);
65e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_TRUE(objdata.find(&buf2));
66e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_EQ(buf, buf2);
67e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_FALSE(objdata.find(&i));
68e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_TRUE(objdata.find(&obj));
69e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_TRUE(obj == buf);
70e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
71e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * obj = buf;
72e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * objdata.set(obj); // storing as sp<RefBase>
73e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_FALSE(objdata.find(&buf2));  // not stored as ABuffer(!)
74e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * EXPECT_TRUE(objdata.find(&obj));
75e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
76e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
77e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/// \cond Internal
78e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
79e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
80e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Helper class to call constructor and destructor for a specific type in AUnion.
81e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * This class is needed as member function specialization is not allowed for a
82e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * templated class.
83e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
8485042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AUnion_impl {
85e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
86e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Calls placement constuctor for type T with arbitrary arguments for a storage at an address.
87e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Storage MUST be large enough to contain T.
88e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Also clears the slack space after type T. \todo This is not technically needed, so we may
89e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * choose to do this just for debugging.
90e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
91e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param totalSize size of the storage
92e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param addr      pointer to where object T should be constructed
93e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param args      arbitrary arguments for constructor
94e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
95e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename T, typename ...Args>
96e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void emplace(size_t totalSize, T *addr, Args&&... args) {
97e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        new(addr)T(std::forward<Args>(args)...);
98e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        // clear slack space - this is not technically required
99e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        constexpr size_t size = sizeof(T);
100e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        memset(reinterpret_cast<uint8_t*>(addr) + size, 0, totalSize - size);
101e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
102e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
103e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
104e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Calls destuctor for an object of type T located at a specific address.
105e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
106e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \note we do not clear the storage in this case as the storage should not be used
107e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * until another object is placed there, at which case the storage will be cleared.
108e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
109e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param addr    pointer to where object T is stored
110e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
111e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename T>
112e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void del(T *addr) {
113e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        addr->~T();
114e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
115e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar};
116e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
117e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/** Constructor specialization for void type */
118e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<>
11985042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos MolnarHIDE inline void _AUnion_impl::emplace<void>(size_t totalSize, void *addr) {
120e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    memset(addr, 0, totalSize);
121e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar}
122e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
123e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/** Destructor specialization for void type */
124e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<>
12585042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos MolnarHIDE inline void _AUnion_impl::del<void>(void *) {
126e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar}
127e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
128e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/// \endcond
129e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
130e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
131e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * A templated union class that can contain specific types of data, and provides
132e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * constructors, destructor and access methods strictly for those types.
133e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
134e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \note This class is VERY UNSAFE compared to a union, but it allows non-POD unions.
135e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * In particular care must be taken that methods are called in a careful order to
136e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * prevent accessing objects of one type as another type. This class provides no
137e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * facilities to help with this ordering. This is meant to be wrapped by safer
138e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * utility classes that do that.
139e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
140e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param Ts types stored in this union.
141e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
142e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename ...Ts>
143e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct AUnion {
144e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarprivate:
145e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    using _type = typename std::aligned_union<0, Ts...>::type; ///< storage type
146e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    _type mValue;                                              ///< storage
147e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
148e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarpublic:
149e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
150e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Constructs an object of type T with arbitrary arguments in this union. After this call,
151e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * this union will contain this object.
152e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
153e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * This method MUST be called only when either 1) no object or 2) a void object (equivalent to
154e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * no object) is contained in this union.
155e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
156e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param T     type of object to be constructed. This must be one of the template parameters of
157e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *              the union class with the same cv-qualification, or void.
158e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param args  arbitrary arguments for the constructor
159e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
160e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<
161e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            typename T, typename ...Args,
162e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            typename=typename std::enable_if<is_one_of<T, void, Ts...>::value>::type>
163e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline void emplace(Args&&... args) {
164e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        _AUnion_impl::emplace(
165e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                sizeof(_type), reinterpret_cast<T*>(&mValue), std::forward<Args>(args)...);
166e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
167e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
168e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
169e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Destructs an object of type T in this union. After this call, this union will contain no
170e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * object.
171e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
172e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * This method MUST be called only when this union contains an object of type T.
173e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
174e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param T     type of object to be destructed. This must be one of the template parameters of
175e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *              the union class with the same cv-qualification, or void.
176e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
177e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<
178e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            typename T,
179e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            typename=typename std::enable_if<is_one_of<T, void, Ts...>::value>::type>
180e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline void del() {
181e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        _AUnion_impl::del(reinterpret_cast<T*>(&mValue));
182e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
183e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
184e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
185e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Returns a const reference to the object of type T in this union.
186e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
187e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * This method MUST be called only when this union contains an object of type T.
188e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
189e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param T     type of object to be returned. This must be one of the template parameters of
190e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *              the union class with the same cv-qualification.
191e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
192e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<
193e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            typename T,
194e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type>
195e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline const T &get() const {
196e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        return *reinterpret_cast<const T*>(&mValue);
197e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
198e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
199e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
200e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Returns a reference to the object of type T in this union.
201e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
202e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * This method MUST be called only when this union contains an object of type T.
203e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
204e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param T     type of object to be returned. This must be one of the template parameters of
205e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *              the union class with the same cv-qualification.
206e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
207e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename T>
208e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline T &get() {
209e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        return *reinterpret_cast<T*>(&mValue);
210e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
211e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar};
212e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
213e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
214e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Helper utility class that copies an object of type T to a destination.
215e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
216e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * T must be copy assignable or copy constructible.
217e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
218e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * It provides:
219e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
220e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * void assign(T*, const U&) // for copiable types - this leaves the source unchanged, hence const.
221e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
222e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param T type of object to assign to
223e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
224e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<
225e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        typename T,
226e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        bool=std::is_copy_assignable<T>::value>
22785042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AData_copier {
228e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    static_assert(std::is_copy_assignable<T>::value, "T must be copy assignable here");
229e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
230e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
231e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Copies src to data without modifying data.
232e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
233e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param data pointer to destination
234e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param src source object
235e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
236e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void assign(T *data, const T &src) {
237e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        *data = src;
238e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
239e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
240e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename U>
241e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    using enable_if_T_is_same_as = typename std::enable_if<std::is_same<U, T>::value>::type;
242e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
243e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
244e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Downcast specializations for sp<>, shared_ptr<> and weak_ptr<>
245e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
246e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Tp, typename U, typename=enable_if_T_is_same_as<sp<Tp>>>
247e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void assign(sp<Tp> *data, const sp<U> &src) {
248e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        *data = static_cast<Tp*>(src.get());
249e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
250e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
251e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Tp, typename U, typename=enable_if_T_is_same_as<wp<Tp>>>
252e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void assign(wp<Tp> *data, const wp<U> &src) {
253e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        sp<U> __tmp = src.promote();
254e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        *data = static_cast<Tp*>(__tmp.get());
255e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
256e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
257e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Tp, typename U, typename=enable_if_T_is_same_as<sp<Tp>>>
258e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void assign(sp<Tp> *data, sp<U> &&src) {
259e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        sp<U> __tmp = std::move(src); // move src out as get cannot
260e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        *data = static_cast<Tp*>(__tmp.get());
261e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
262e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
263e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::shared_ptr<Tp>>>
264e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void assign(std::shared_ptr<Tp> *data, const std::shared_ptr<U> &src) {
265e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        *data = std::static_pointer_cast<Tp>(src);
266e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
267e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
268e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::shared_ptr<Tp>>>
269e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void assign(std::shared_ptr<Tp> *data, std::shared_ptr<U> &&src) {
270e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        std::shared_ptr<U> __tmp = std::move(src); // move src out as static_pointer_cast cannot
271e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        *data = std::static_pointer_cast<Tp>(__tmp);
272e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
273e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
274e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::weak_ptr<Tp>>>
275e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void assign(std::weak_ptr<Tp> *data, const std::weak_ptr<U> &src) {
276e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        *data = std::static_pointer_cast<Tp>(src.lock());
277e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
278e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
279e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    // shared_ptrs are implicitly convertible to weak_ptrs but not vice versa, but picking the
280e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    // first compatible type in Ts requires having shared_ptr types before weak_ptr types, so that
281e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    // they are stored as shared_ptrs.
282e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
283e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Provide sensible error message if encountering shared_ptr/weak_ptr ambiguity. This method
284e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * is not enough to detect this, only if someone is trying to find the shared_ptr.
285e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
286e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Tp, typename U>
287e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void assign(std::shared_ptr<Tp> *, const std::weak_ptr<U> &) {
288e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static_assert(std::is_same<Tp, void>::value,
289e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                      "shared/weak pointer ambiguity. move shared ptr types before weak_ptrs");
290e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
291e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar};
292e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
293e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
294e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization for non copy assignable, but copy constructible types.
295e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
296e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \todo Test this. No basic classes are copy constructible but not assignable.
297e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
298e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
299e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename T>
30085042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AData_copier<T, false> {
301e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    static_assert(!std::is_copy_assignable<T>::value, "T must not be copy assignable here");
302e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible here");
303e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
304e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void copy(T *data, const T &src) {
305e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        data->~T();
306e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        new(data)T(src);
307e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
308e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar};
309e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
310e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
311e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Helper utility class that moves an object of type T to a destination.
312e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
313e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * T must be move assignable or move constructible.
314e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
315e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * It provides multiple methods:
316e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
317e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * void assign(T*, T&&)
318e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
319e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param T type of object to assign
320e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
321e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<
322e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        typename T,
323e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        bool=std::is_move_assignable<T>::value>
32485042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AData_mover {
325e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    static_assert(std::is_move_assignable<T>::value, "T must be move assignable here");
326e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
327e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
328e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Moves src to data while likely modifying it.
329e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
330e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param data pointer to destination
331e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param src source object
332e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
333e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void assign(T *data, T &&src) {
334e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        *data = std::move(src);
335e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
336e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
337e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename U>
338e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    using enable_if_T_is_same_as = typename std::enable_if<std::is_same<U, T>::value>::type;
339e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
340e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
341e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Downcast specializations for sp<>, shared_ptr<> and weak_ptr<>
342e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
343e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Tp, typename U, typename=enable_if_T_is_same_as<sp<Tp>>>
344e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void assign(sp<Tp> *data, sp<U> &&src) {
345e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        sp<U> __tmp = std::move(src); // move src out as get cannot
346e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        *data = static_cast<Tp*>(__tmp.get());
347e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
348e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
349e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::shared_ptr<Tp>>>
350e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void assign(std::shared_ptr<Tp> *data, std::shared_ptr<U> &&src) {
351e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        std::shared_ptr<U> __tmp = std::move(src); // move src out as static_pointer_cast cannot
352e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        *data = std::static_pointer_cast<Tp>(__tmp);
353e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
354e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
355e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Tp, typename Td, typename U, typename Ud,
356e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            typename=enable_if_T_is_same_as<std::unique_ptr<Tp, Td>>>
357e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void assign(std::unique_ptr<Tp, Td> *data, std::unique_ptr<U, Ud> &&src) {
358e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        *data = std::unique_ptr<Tp, Td>(static_cast<Tp*>(src.release()));
359e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
360e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
361e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    // shared_ptrs are implicitly convertible to weak_ptrs but not vice versa, but picking the
362e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    // first compatible type in Ts requires having shared_ptr types before weak_ptr types, so that
363e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    // they are stored as shared_ptrs.
364e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
365e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Provide sensible error message if encountering shared_ptr/weak_ptr ambiguity. This method
366e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * is not enough to detect this, only if someone is trying to remove the shared_ptr.
367e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
368e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Tp, typename U>
369e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void assign(std::shared_ptr<Tp> *, std::weak_ptr<U> &&) {
370e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static_assert(std::is_same<Tp, void>::value,
371e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                      "shared/weak pointer ambiguity. move shared ptr types before weak_ptrs");
372e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
373e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
374e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    // unique_ptrs are implicitly convertible to shared_ptrs but not vice versa, but picking the
375e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    // first compatible type in Ts requires having unique_ptrs types before shared_ptrs types, so
376e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    // that they are stored as unique_ptrs.
377e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
378e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Provide sensible error message if encountering shared_ptr/unique_ptr ambiguity. This method
379e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * is not enough to detect this, only if someone is trying to remove the unique_ptr.
380e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
381e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Tp, typename U>
382e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void assign(std::unique_ptr<Tp> *, std::shared_ptr<U> &&) {
383e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static_assert(std::is_same<Tp, void>::value,
384e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                      "unique/shared pointer ambiguity. move unique ptr types before shared_ptrs");
385e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
386e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar};
387e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
388e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
389e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization for non move assignable, but move constructible types.
390e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
391e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \todo Test this. No basic classes are move constructible but not assignable.
392e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
393e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
394e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename T>
39585042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AData_mover<T, false> {
396e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    static_assert(!std::is_move_assignable<T>::value, "T must not be move assignable here");
397e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    static_assert(std::is_move_constructible<T>::value, "T must be move constructible here");
398e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
399e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static void assign(T *data, T &&src) {
400e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        data->~T();
401e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        new(data)T(std::move(src));
402e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
403e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar};
404e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
405e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
406e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Helper template that deletes an object of a specific type (member) in an AUnion.
407e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
408e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param Flagger type flagger class (see AData)
409e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param U AUnion object in which the member should be deleted
410e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * \param Ts types to consider for the member
411e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
412e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename Flagger, typename U, typename ...Ts>
41385042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AData_deleter;
414e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
415e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
416e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization when there are still types to consider (T and rest)
417e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
418e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename Flagger, typename U, typename T, typename ...Ts>
41985042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AData_deleter<Flagger, U, T, Ts...> {
420e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    static bool del(typename Flagger::type flags, U &data) {
421e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
422e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            data.template del<T>();
423e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return true;
424e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
425e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        return _AData_deleter<Flagger, U, Ts...>::del(flags, data);
426e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
427e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar};
428e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
429e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
430e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Template specialization when there are no more types to consider.
431e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
432e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename Flagger, typename U>
43385042380bf7ee3a43eb4cccacdaadfbbafc1522fLajos Molnarstruct HIDE _AData_deleter<Flagger, U> {
434e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    inline static bool del(typename Flagger::type, U &) {
435e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        return false;
436e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    }
437e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar};
438e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
439e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar/**
440e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Container that can store an arbitrary object of a set of specified types.
441e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
442e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * This struct is an outer class that contains various inner classes based on desired type
443e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * strictness. The following inner classes are supported:
444e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
445e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<types...>::Basic   - strict type support using uint32_t flag.
446e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
447e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<types...>::Strict<Flag> - strict type support using custom flag.
448e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<types...>::Relaxed<Flag, MaxSize, Align>
449e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *                          - relaxed type support with compatible (usually derived) class support
450e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *                            for pointer types with added size checking for minimal additional
451e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *                            safety.
452e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
453e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<types...>::RelaxedBasic - strict type support using uint32_t flag.
454e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
455e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<types...>::Custom<flagger> - custom type support (flaggers determine the supported types
456e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *                                    and the base type to use for each)
457e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
458e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
459e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename ...Ts>
460e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct AData {
461e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarprivate:
462e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    static_assert(are_unique<Ts...>::value, "types must be unique");
463e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
464e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    static constexpr size_t num_types = sizeof...(Ts); ///< number of types to support
465e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
466e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarpublic:
467e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
468e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Default (strict) type flagger provided.
469e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
470e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * The default flagger simply returns the index of the type within Ts, or 0 for void.
471e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
472e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Type flaggers return a flag for a supported type.
473e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
474e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * They must provide:
475e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
476e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * - a flagFor(T*) method for supported types _and_ for T=void. T=void is used to mark that no
477e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *   object is stored in the container. For this, an arbitrary unique value may be returned.
478e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * - a mask field that contains the flag mask.
479e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * - a canDeleteAs(Flag, Flag) flag comparison method that checks if a type of a flag can be
480e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *   deleted as another type.
481e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
482e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param Flag the underlying unsigned integral to use for the flags.
483e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
484e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Flag>
485e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    struct flagger {
486e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    private:
487e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static_assert(std::is_unsigned<Flag>::value, "Flag must be unsigned");
488e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static_assert(std::is_integral<Flag>::value, "Flag must be an integral type");
489e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
490e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag count = num_types + 1;
491e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
492e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    public:
493e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        typedef Flag type; ///< flag type
494e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
495e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag mask = _Flagged_helper::minMask<Flag>(count); ///< flag mask
496e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
497e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
498e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Return the stored type for T. This is itself.
499e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
500e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
501e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        struct store {
502e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            typedef T as_type; ///< the base type that T is stored as
503e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        };
504e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
505e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
506e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Constexpr method that returns if two flags are compatible for deletion.
507e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
508e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param objectFlag flag for object to be deleted
509e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param deleteFlag flag for type that object is to be deleted as
510e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
511e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr bool canDeleteAs(Flag objectFlag, Flag deleteFlag) {
512e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            // default flagger requires strict type equality
513e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return objectFlag == deleteFlag;
514e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
515e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
516e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
517e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Constexpr method that returns the flag to use for a given type.
518e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
519e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Function overload for void*.
520e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
521e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(void*) {
522e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return 0u;
523e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
524e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
525e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
526e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Constexpr method that returns the flag to use for a given supported type (T).
527e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
528e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T, typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type>
529e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(T*) {
530e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return find_first<T, Ts...>::index;
531e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
532e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    };
533e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
534e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
535e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Relaxed flagger returns the index of the type within Ts. However, for pointers T* it returns
536e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * the first type in Ts that T* can be converted into (this is normally a base type, but also
537e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * works for sp<>, shared_ptr<> or unique_ptr<>). For a bit more strictness, the flag also
538e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * contains the size of the class to avoid finding objects that were stored as a different
539e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * derived class of the same base class.
540e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
541e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Flag is basically the index of the (base) type in Ts multiplied by the max size stored plus
542e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * the size of the type (divided by alignment) for derived pointer types.
543e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
544e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param MaxSize max supported size for derived class pointers
545e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param Align alignment to assume for derived class pointers
546e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
547e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Flag, size_t MaxSize=1024, size_t Align=4>
548e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    struct relaxed_flagger {
549e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    private:
550e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static_assert(std::is_unsigned<Flag>::value, "Flag must be unsigned");
551e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static_assert(std::is_integral<Flag>::value, "Flag must be an integral type");
552e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
553e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag count = num_types + 1;
554e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static_assert(std::numeric_limits<Flag>::max() / count > (MaxSize / Align),
555e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                      "not enough bits to fit into flag");
556e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
557e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag max_size_stored = MaxSize / Align + 1;
558e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
559e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        // T can be converted if it's size is <= MaxSize and it can be converted to one of the Ts
560e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T, size_t size>
561e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        using enable_if_can_be_converted = typename std::enable_if<
562e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                (size / Align < max_size_stored
563e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                        && find_first_convertible_to<T, Ts...>::index)>::type;
564e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
565e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
566e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename W, typename T, typename=enable_if_can_be_converted<W, sizeof(T)>>
567e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag relaxedFlagFor(W*, T*) {
568e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return find_first_convertible_to<W, Ts...>::index * max_size_stored
569e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    + (is_one_of<W, Ts...>::value ? 0 : (sizeof(T) / Align));
570e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
571e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
572e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    public:
573e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        typedef Flag type; ///< flag type
574e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
575e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag mask =
576e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            _Flagged_helper::minMask<Flag>(count * max_size_stored); ///< flag mask
577e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
578e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
579e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Constexpr method that returns if two flags are compatible for deletion.
580e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
581e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param objectFlag flag for object to be deleted
582e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param deleteFlag flag for type that object is to be deleted as
583e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
584e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr bool canDeleteAs(Flag objectFlag, Flag deleteFlag) {
585e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            // can delete if objects have the same base type
586e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return
587e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                objectFlag / max_size_stored == deleteFlag / max_size_stored &&
588e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                (deleteFlag % max_size_stored) == 0;
589e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
590e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
591e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
592e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Constexpr method that returns the flag to use for a given type.
593e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
594e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Function overload for void*.
595e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
596e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(void*) {
597e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return 0u;
598e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
599e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
600e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
601e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Constexpr method that returns the flag to use for a given supported type (T).
602e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
603e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * This is a member method to enable both overloading as well as template specialization.
604e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
605e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T, typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type>
606e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(T*) {
607e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return find_first<T, Ts...>::index * max_size_stored;
608e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
609e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
610e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
611e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * For precaution, we only consider converting pointers to their base classes.
612e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
613e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
614e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
615e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Template specialization for derived class pointers and managed pointers.
616e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
617e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
618e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(T**p) { return relaxedFlagFor(p, (T*)0); }
619e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
620e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(std::shared_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); }
621e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
622e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(std::unique_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); }
623e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
624e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(std::weak_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); }
625e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
626e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(sp<T>*p) { return relaxedFlagFor(p, (T*)0); }
627e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
628e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(wp<T>*p) { return relaxedFlagFor(p, (T*)0); }
629e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
630e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
631e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Type support template that provodes the stored type for T.
632e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * This is itself if it is one of Ts, or the first type in Ts that T is convertible to.
633e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
634e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * NOTE: This template may provide a base class for an unsupported type. Support is
635e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * determined by flagFor().
636e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
637e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
638e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        struct store {
639e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            typedef typename std::conditional<
640e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    is_one_of<T, Ts...>::value,
641e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    T,
642e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    typename find_first_convertible_to<T, Ts...>::type>::type as_type;
643e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        };
644e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    };
645e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
646e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
647e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Implementation of AData.
648e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
649e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Flagger>
650e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    struct Custom : protected Flagged<AUnion<Ts...>, typename Flagger::type, Flagger::mask> {
651e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        using data_t = AUnion<Ts...>;
652e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        using base_t = Flagged<AUnion<Ts...>, typename Flagger::type, Flagger::mask>;
653e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
654e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
655e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Constructor. Initializes this to a container that does not contain any object.
656e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
657e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        Custom() : base_t(Flagger::flagFor((void*)0)) { }
658e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
659e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
660e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Removes the contained object, if any.
661e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
662e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        ~Custom() {
663e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            if (!this->clear()) {
664e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                __builtin_trap();
665e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                // std::cerr << "could not delete data of type " << this->flags() << std::endl;
666e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            }
667e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
668e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
669e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
670e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Returns whether there is any object contained.
671e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
672e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        inline bool used() const {
673e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return this->flags() != Flagger::flagFor((void*)0);
674e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
675e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
676e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
677e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Removes the contained object, if any. Returns true if there are no objects contained,
678e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * or false on any error (this is highly unexpected).
679e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
680e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        bool clear() {
681e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            if (this->used()) {
682e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                if (_AData_deleter<Flagger, data_t, Ts...>::del(this->flags(), this->get())) {
683e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    this->setFlags(Flagger::flagFor((void*)0));
684e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    return true;
685e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                }
686e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                return false;
687e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            }
688e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return true;
689e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
690e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
691e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
692e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        using is_supported_by_flagger =
693e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            typename std::enable_if<Flagger::flagFor((T*)0) != Flagger::flagFor((void*)0)>::type;
694e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
695e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
696e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Checks if there is a copiable object of type T in this container. If there is, it copies
697e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * that object into the provided address and returns true. Otherwise, it does nothing and
698e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * returns false.
699e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
700e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * This method normally requires a flag equality between the stored and retrieved types.
701e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * However, it also allows retrieving the stored object as the stored type
702e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * (usually base type).
703e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
704e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param T type of object to sought
705e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param data address at which the object should be retrieved
706e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
707e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \return true if the object was retrieved. false if it was not.
708e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
709e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<
710e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename T,
711e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename=is_supported_by_flagger<T>>
712e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        bool find(T *data) const {
713e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            using B = typename Flagger::template store<T>::as_type;
714e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            if (this->flags() == Flagger::flagFor((T*)0) ||
715e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                Flagger::canDeleteAs(this->flags(), Flagger::flagFor((T*)0))) {
716e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                _AData_copier<T>::assign(data, this->get().template get<B>());
717e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                return true;
718e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            }
719e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return false;
720e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
721e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
722e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
723e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Checks if there is an object of type T in this container. If there is, it moves that
724e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * object into the provided address and returns true. Otherwise, it does nothing and returns
725e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * false.
726e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
727e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * This method normally requires a flag equality between the stored and retrieved types.
728e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * However, it also allows retrieving the stored object as the stored type
729e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * (usually base type).
730e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
731e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param T type of object to sought
732e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param data address at which the object should be retrieved.
733e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
734e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \return true if the object was retrieved. false if it was not.
735e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
736e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<
737e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename T,
738e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename=is_supported_by_flagger<T>>
739e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        bool remove(T *data) {
740e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            using B = typename Flagger::template store<T>::as_type;
741e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            if (this->flags() == Flagger::flagFor((T*)0) ||
742e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                Flagger::canDeleteAs(this->flags(), Flagger::flagFor((T*)0))) {
743e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                _AData_mover<T>::assign(data, std::move(this->get().template get<B>()));
744e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                return true;
745e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            }
746e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return false;
747e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
748e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
749e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
750e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Stores an object into this container by copying. If it was successful, returns true.
751e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Otherwise, (e.g. it could not destroy the already stored object) it returns false. This
752e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * latter would be highly unexpected.
753e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
754e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param T type of object to store
755e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param data object to store
756e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
757e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \return true if the object was stored. false if it was not.
758e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
759e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<
760e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename T,
761e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename=is_supported_by_flagger<T>,
762e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename=typename std::enable_if<
763e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                        std::is_copy_constructible<T>::value ||
764e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                        (std::is_default_constructible<T>::value &&
765e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                                std::is_copy_assignable<T>::value)>::type>
766e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        bool set(const T &data) {
767e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            using B = typename Flagger::template store<T>::as_type;
768e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
769e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            // if already contains an object of this type, simply assign
770e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            if (this->flags() == Flagger::flagFor((T*)0) && std::is_same<T, B>::value) {
771e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                _AData_copier<B>::assign(&this->get().template get<B>(), data);
772e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                return true;
773e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            } else if (this->used()) {
774e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                // destroy previous object
775e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                if (!this->clear()) {
776e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    return false;
777e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                }
778e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            }
779e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            this->get().template emplace<B>(data);
780e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            this->setFlags(Flagger::flagFor((T *)0));
781e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return true;
782e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
783e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
784e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
785e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Moves an object into this container. If it was successful, returns true. Otherwise,
786e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * (e.g. it could not destroy the already stored object) it returns false. This latter
787e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * would be highly unexpected.
788e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
789e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param T type of object to store
790e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param data object to store
791e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
792e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \return true if the object was stored. false if it was not.
793e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
794e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<
795e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename T,
796e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename=is_supported_by_flagger<T>>
797e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        bool set(T &&data) {
798e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            using B = typename Flagger::template store<T>::as_type;
799e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
800e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            // if already contains an object of this type, simply assign
801e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            if (this->flags() == Flagger::flagFor((T*)0) && std::is_same<T, B>::value) {
802e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                _AData_mover<B>::assign(&this->get().template get<B>(), std::forward<T&&>(data));
803e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                return true;
804e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            } else if (this->used()) {
805e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                // destroy previous object
806e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                if (!this->clear()) {
807e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    return false;
808e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                }
809e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            }
810e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            this->get().template emplace<B>(std::forward<T&&>(data));
811e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            this->setFlags(Flagger::flagFor((T *)0));
812e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return true;
813e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
814e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    };
815e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
816e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
817e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Basic AData using the default type flagger and requested flag type.
818e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
819e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param Flag desired flag type to use. Must be an unsigned and std::integral type.
820e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
821e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Flag>
822e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    using Strict = Custom<flagger<Flag>>;
823e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
824e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
825e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Basic AData using the default type flagger and uint32_t flag.
826e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
827e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    using Basic = Strict<uint32_t>;
828e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
829e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
830e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * AData using the relaxed type flagger for max size and requested flag type.
831e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
832e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param Flag desired flag type to use. Must be an unsigned and std::integral type.
833e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
834e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Flag, size_t MaxSize = 1024, size_t Align = 4>
835e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    using Relaxed = Custom<relaxed_flagger<Flag, MaxSize, Align>>;
836e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
837e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
838e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Basic AData using the relaxed type flagger and uint32_t flag.
839e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
840e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    using RelaxedBasic = Relaxed<uint32_t>;
841e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar};
842e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
843e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar}  // namespace android
844e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
845e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#endif  // STAGEFRIGHT_FOUNDATION_A_DATA_H_
846e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
847