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/**
440f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar * Helper template that copy assigns an object of a specific type (member) in an
441f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar * AUnion.
442f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar *
443f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar * \param Flagger type flagger class (see AData)
444f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar * \param U AUnion object in which the member should be copy assigned
445f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar * \param Ts types to consider for the member
446f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar */
447f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnartemplate<typename Flagger, typename U, typename ...Ts>
448f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnarstruct HIDE _AData_copy_assigner;
449f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar
450f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar/**
451f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar * Template specialization when there are still types to consider (T and rest)
452f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar */
453f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnartemplate<typename Flagger, typename U, typename T, typename ...Ts>
454f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnarstruct HIDE _AData_copy_assigner<Flagger, U, T, Ts...> {
455f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar    static bool assign(typename Flagger::type flags, U &dst, const U &src) {
456f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible");
457f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        // if we can delete as, we can also assign as
458f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
459f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar            dst.template emplace<T>(src.template get<T>());
460f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar            return true;
461f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        }
462f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        return _AData_copy_assigner<Flagger, U, Ts...>::assign(flags, dst, src);
463f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar    }
464f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar};
465f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar
466f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar/**
467f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar * Template specialization when there are no more types to consider.
468f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar */
469f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnartemplate<typename Flagger, typename U>
470f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnarstruct HIDE _AData_copy_assigner<Flagger, U> {
471f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar    inline static bool assign(typename Flagger::type, U &, const U &) {
472f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        return false;
473f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar    }
474f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar};
475f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar
476f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar/**
477f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar * Helper template that move assigns an object of a specific type (member) in an
478f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar * AUnion.
479f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar *
480f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar * \param Flagger type flagger class (see AData)
481f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar * \param U AUnion object in which the member should be copy assigned
482f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar * \param Ts types to consider for the member
483f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar */
484f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnartemplate<typename Flagger, typename U, typename ...Ts>
485f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnarstruct HIDE _AData_move_assigner;
486f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar
487f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar/**
488f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar * Template specialization when there are still types to consider (T and rest)
489f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar */
490f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnartemplate<typename Flagger, typename U, typename T, typename ...Ts>
491f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnarstruct HIDE _AData_move_assigner<Flagger, U, T, Ts...> {
492f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar    template<typename V = T>
493f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar    static typename std::enable_if<std::is_move_constructible<V>::value, bool>::type
494f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar    assign(typename Flagger::type flags, U &dst, U &src) {
495f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        // if we can delete as, we can also assign as
496f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
497f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar            dst.template emplace<T>(std::move(src.template get<T>()));
498f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar            return true;
499f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        }
500f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        return _AData_move_assigner<Flagger, U, Ts...>::assign(flags, dst, src);
501f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar    }
502f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar
503f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar    // Fall back to copy construction if T is not move constructible
504f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar    template<typename V = T>
505f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar    static typename std::enable_if<!std::is_move_constructible<V>::value, bool>::type
506f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar    assign(typename Flagger::type flags, U &dst, U &src) {
507f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible");
508f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        // if we can delete as, we can also assign as
509f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
510f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar            dst.template emplace<T>(src.template get<T>());
511f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar            return true;
512f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        }
513f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        return _AData_move_assigner<Flagger, U, Ts...>::assign(flags, dst, src);
514f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar    }
515f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar};
516f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar
517f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar/**
518f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar * Template specialization when there are no more types to consider.
519f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar */
520f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnartemplate<typename Flagger, typename U>
521f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnarstruct HIDE _AData_move_assigner<Flagger, U> {
522f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar    inline static bool assign(typename Flagger::type, U &, U &) {
523f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        return false;
524f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar    }
525f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar};
526f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar
527f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar/**
528e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * Container that can store an arbitrary object of a set of specified types.
529e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
530e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * This struct is an outer class that contains various inner classes based on desired type
531e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * strictness. The following inner classes are supported:
532e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
533e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<types...>::Basic   - strict type support using uint32_t flag.
534e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
535e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<types...>::Strict<Flag> - strict type support using custom flag.
536e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<types...>::Relaxed<Flag, MaxSize, Align>
537e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *                          - relaxed type support with compatible (usually derived) class support
538e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *                            for pointer types with added size checking for minimal additional
539e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *                            safety.
540e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
541e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<types...>::RelaxedBasic - strict type support using uint32_t flag.
542e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
543e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar * AData<types...>::Custom<flagger> - custom type support (flaggers determine the supported types
544e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *                                    and the base type to use for each)
545e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar *
546e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar */
547e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnartemplate<typename ...Ts>
548e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarstruct AData {
549e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarprivate:
550e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    static_assert(are_unique<Ts...>::value, "types must be unique");
551e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
552e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    static constexpr size_t num_types = sizeof...(Ts); ///< number of types to support
553e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
554e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnarpublic:
555e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
556e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Default (strict) type flagger provided.
557e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
558e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * The default flagger simply returns the index of the type within Ts, or 0 for void.
559e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
560e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Type flaggers return a flag for a supported type.
561e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
562e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * They must provide:
563e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
564e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * - a flagFor(T*) method for supported types _and_ for T=void. T=void is used to mark that no
565e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *   object is stored in the container. For this, an arbitrary unique value may be returned.
566e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * - a mask field that contains the flag mask.
567e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * - a canDeleteAs(Flag, Flag) flag comparison method that checks if a type of a flag can be
568e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *   deleted as another type.
569e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
570e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param Flag the underlying unsigned integral to use for the flags.
571e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
572e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Flag>
573e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    struct flagger {
574e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    private:
575e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static_assert(std::is_unsigned<Flag>::value, "Flag must be unsigned");
576e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static_assert(std::is_integral<Flag>::value, "Flag must be an integral type");
577e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
578e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag count = num_types + 1;
579e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
580e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    public:
581e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        typedef Flag type; ///< flag type
582e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
583e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag mask = _Flagged_helper::minMask<Flag>(count); ///< flag mask
584e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
585e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
586e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Return the stored type for T. This is itself.
587e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
588e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
589e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        struct store {
590e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            typedef T as_type; ///< the base type that T is stored as
591e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        };
592e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
593e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
594e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Constexpr method that returns if two flags are compatible for deletion.
595e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
596e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param objectFlag flag for object to be deleted
597e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param deleteFlag flag for type that object is to be deleted as
598e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
599e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr bool canDeleteAs(Flag objectFlag, Flag deleteFlag) {
600e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            // default flagger requires strict type equality
601e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return objectFlag == deleteFlag;
602e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
603e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
604e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
605e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Constexpr method that returns the flag to use for a given type.
606e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
607e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Function overload for void*.
608e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
609e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(void*) {
610e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return 0u;
611e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
612e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
613e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
614e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Constexpr method that returns the flag to use for a given supported type (T).
615e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
616e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T, typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type>
617e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(T*) {
618e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return find_first<T, Ts...>::index;
619e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
620e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    };
621e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
622e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
623e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Relaxed flagger returns the index of the type within Ts. However, for pointers T* it returns
624e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * the first type in Ts that T* can be converted into (this is normally a base type, but also
625e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * works for sp<>, shared_ptr<> or unique_ptr<>). For a bit more strictness, the flag also
626e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * contains the size of the class to avoid finding objects that were stored as a different
627e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * derived class of the same base class.
628e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
629e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Flag is basically the index of the (base) type in Ts multiplied by the max size stored plus
630e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * the size of the type (divided by alignment) for derived pointer types.
631e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
632e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param MaxSize max supported size for derived class pointers
633e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param Align alignment to assume for derived class pointers
634e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
635e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Flag, size_t MaxSize=1024, size_t Align=4>
636e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    struct relaxed_flagger {
637e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    private:
638e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static_assert(std::is_unsigned<Flag>::value, "Flag must be unsigned");
639e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static_assert(std::is_integral<Flag>::value, "Flag must be an integral type");
640e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
641e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag count = num_types + 1;
642e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static_assert(std::numeric_limits<Flag>::max() / count > (MaxSize / Align),
643e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                      "not enough bits to fit into flag");
644e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
645e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag max_size_stored = MaxSize / Align + 1;
646e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
647e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        // T can be converted if it's size is <= MaxSize and it can be converted to one of the Ts
648e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T, size_t size>
649e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        using enable_if_can_be_converted = typename std::enable_if<
650e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                (size / Align < max_size_stored
651e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                        && find_first_convertible_to<T, Ts...>::index)>::type;
652e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
653e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
654e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename W, typename T, typename=enable_if_can_be_converted<W, sizeof(T)>>
655e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag relaxedFlagFor(W*, T*) {
656e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return find_first_convertible_to<W, Ts...>::index * max_size_stored
657e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    + (is_one_of<W, Ts...>::value ? 0 : (sizeof(T) / Align));
658e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
659e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
660e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    public:
661e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        typedef Flag type; ///< flag type
662e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
663e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag mask =
664e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            _Flagged_helper::minMask<Flag>(count * max_size_stored); ///< flag mask
665e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
666e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
667e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Constexpr method that returns if two flags are compatible for deletion.
668e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
669e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param objectFlag flag for object to be deleted
670e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param deleteFlag flag for type that object is to be deleted as
671e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
672e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr bool canDeleteAs(Flag objectFlag, Flag deleteFlag) {
673e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            // can delete if objects have the same base type
674e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return
675e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                objectFlag / max_size_stored == deleteFlag / max_size_stored &&
676e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                (deleteFlag % max_size_stored) == 0;
677e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
678e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
679e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
680e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Constexpr method that returns the flag to use for a given type.
681e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
682e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Function overload for void*.
683e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
684e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(void*) {
685e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return 0u;
686e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
687e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
688e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
689e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Constexpr method that returns the flag to use for a given supported type (T).
690e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
691e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * This is a member method to enable both overloading as well as template specialization.
692e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
693e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T, typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type>
694e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(T*) {
695e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return find_first<T, Ts...>::index * max_size_stored;
696e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
697e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
698e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
699e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * For precaution, we only consider converting pointers to their base classes.
700e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
701e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
702e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
703e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Template specialization for derived class pointers and managed pointers.
704e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
705e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
706e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(T**p) { return relaxedFlagFor(p, (T*)0); }
707e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
708e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(std::shared_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); }
709e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
710e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(std::unique_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); }
711e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
712e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(std::weak_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); }
713e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
714e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(sp<T>*p) { return relaxedFlagFor(p, (T*)0); }
715e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
716e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        static constexpr Flag flagFor(wp<T>*p) { return relaxedFlagFor(p, (T*)0); }
717e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
718e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
719e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Type support template that provodes the stored type for T.
720e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * This is itself if it is one of Ts, or the first type in Ts that T is convertible to.
721e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
722e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * NOTE: This template may provide a base class for an unsupported type. Support is
723e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * determined by flagFor().
724e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
725e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
726e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        struct store {
727e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            typedef typename std::conditional<
728e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    is_one_of<T, Ts...>::value,
729e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    T,
730e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    typename find_first_convertible_to<T, Ts...>::type>::type as_type;
731e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        };
732e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    };
733e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
734e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
735e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Implementation of AData.
736e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
737e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Flagger>
738e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    struct Custom : protected Flagged<AUnion<Ts...>, typename Flagger::type, Flagger::mask> {
739e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        using data_t = AUnion<Ts...>;
740e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        using base_t = Flagged<AUnion<Ts...>, typename Flagger::type, Flagger::mask>;
741e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
742e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
743e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Constructor. Initializes this to a container that does not contain any object.
744e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
745e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        Custom() : base_t(Flagger::flagFor((void*)0)) { }
746e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
747e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
748f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar         * Copy assignment operator.
749f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar         */
750f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        Custom& operator=(const Custom &o) {
751f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar            if (&o != this) {
752f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                if (this->used() && !this->clear()) {
753f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                    __builtin_trap();
754f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                }
755f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                if (o.used()) {
756f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                    if (_AData_copy_assigner<Flagger, data_t, Ts...>::assign(
757f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                            o.flags(), this->get(), o.get())) {
758f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                        this->setFlags(o.flags());
759f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                    } else {
760f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                        __builtin_trap();
761f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                    }
762f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                }
763f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar            }
764f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar            return *this;
765f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        }
766f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar
767f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        /**
768f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar         * Copy constructor.
769f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar         */
770f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        Custom(const Custom &o) : Custom() {
771f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar            *this = o;
772f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        }
773f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar
774f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        /**
775f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar         * Move assignment operator.
776f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar         */
777f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        Custom& operator=(Custom &&o) {
778f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar            if (&o != this) {
779f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                if (this->used() && !this->clear()) {
780f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                    __builtin_trap();
781f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                }
782f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                if (o.used()) {
783f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                    if (_AData_move_assigner<Flagger, data_t, Ts...>::assign(
784f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                            o.flags(), this->get(), o.get())) {
785f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                        this->setFlags(o.flags());
786f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                        o.clear();
787f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                    } else {
788f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                        __builtin_trap();
789f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                    }
790f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar                }
791f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar            }
792f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar            return *this;
793f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        }
794f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar
795f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        /**
796f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar         * Move constructor.
797f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar         */
798f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        Custom(Custom &&o) : Custom() {
799f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar            *this = std::move(o);
800f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        }
801f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar
802f252dd8dc988e8fb4cc4d14c83283625ad225754Lajos Molnar        /**
803e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Removes the contained object, if any.
804e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
805e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        ~Custom() {
806e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            if (!this->clear()) {
807e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                __builtin_trap();
808e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                // std::cerr << "could not delete data of type " << this->flags() << std::endl;
809e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            }
810e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
811e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
812e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
813e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Returns whether there is any object contained.
814e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
815e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        inline bool used() const {
816e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return this->flags() != Flagger::flagFor((void*)0);
817e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
818e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
819e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
820e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Removes the contained object, if any. Returns true if there are no objects contained,
821e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * or false on any error (this is highly unexpected).
822e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
823e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        bool clear() {
824e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            if (this->used()) {
825e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                if (_AData_deleter<Flagger, data_t, Ts...>::del(this->flags(), this->get())) {
826e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    this->setFlags(Flagger::flagFor((void*)0));
827e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    return true;
828e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                }
829e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                return false;
830e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            }
831e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return true;
832e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
833e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
834e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<typename T>
835e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        using is_supported_by_flagger =
836e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            typename std::enable_if<Flagger::flagFor((T*)0) != Flagger::flagFor((void*)0)>::type;
837e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
838e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
839e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Checks if there is a copiable object of type T in this container. If there is, it copies
840e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * that object into the provided address and returns true. Otherwise, it does nothing and
841e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * returns false.
842e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
843e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * This method normally requires a flag equality between the stored and retrieved types.
844e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * However, it also allows retrieving the stored object as the stored type
845e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * (usually base type).
846e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
847e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param T type of object to sought
848e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param data address at which the object should be retrieved
849e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
850e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \return true if the object was retrieved. false if it was not.
851e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
852e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<
853e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename T,
854e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename=is_supported_by_flagger<T>>
855e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        bool find(T *data) const {
856e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            using B = typename Flagger::template store<T>::as_type;
857e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            if (this->flags() == Flagger::flagFor((T*)0) ||
858e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                Flagger::canDeleteAs(this->flags(), Flagger::flagFor((T*)0))) {
859e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                _AData_copier<T>::assign(data, this->get().template get<B>());
860e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                return true;
861e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            }
862e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return false;
863e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
864e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
865e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
866e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Checks if there is an object of type T in this container. If there is, it moves that
867e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * object into the provided address and returns true. Otherwise, it does nothing and returns
868e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * false.
869e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
870e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * This method normally requires a flag equality between the stored and retrieved types.
871e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * However, it also allows retrieving the stored object as the stored type
872e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * (usually base type).
873e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
874e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param T type of object to sought
875e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param data address at which the object should be retrieved.
876e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
877e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \return true if the object was retrieved. false if it was not.
878e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
879e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<
880e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename T,
881e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename=is_supported_by_flagger<T>>
882e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        bool remove(T *data) {
883e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            using B = typename Flagger::template store<T>::as_type;
884e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            if (this->flags() == Flagger::flagFor((T*)0) ||
885e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                Flagger::canDeleteAs(this->flags(), Flagger::flagFor((T*)0))) {
886e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                _AData_mover<T>::assign(data, std::move(this->get().template get<B>()));
887e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                return true;
888e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            }
889e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return false;
890e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
891e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
892e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
893e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Stores an object into this container by copying. If it was successful, returns true.
894e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Otherwise, (e.g. it could not destroy the already stored object) it returns false. This
895e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * latter would be highly unexpected.
896e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
897e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param T type of object to store
898e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param data object to store
899e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
900e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \return true if the object was stored. false if it was not.
901e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
902e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<
903e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename T,
904e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename=is_supported_by_flagger<T>,
905e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename=typename std::enable_if<
906e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                        std::is_copy_constructible<T>::value ||
907e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                        (std::is_default_constructible<T>::value &&
908e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                                std::is_copy_assignable<T>::value)>::type>
909e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        bool set(const T &data) {
910e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            using B = typename Flagger::template store<T>::as_type;
911e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
912e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            // if already contains an object of this type, simply assign
913e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            if (this->flags() == Flagger::flagFor((T*)0) && std::is_same<T, B>::value) {
914e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                _AData_copier<B>::assign(&this->get().template get<B>(), data);
915e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                return true;
916e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            } else if (this->used()) {
917e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                // destroy previous object
918e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                if (!this->clear()) {
919e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    return false;
920e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                }
921e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            }
922e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            this->get().template emplace<B>(data);
923e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            this->setFlags(Flagger::flagFor((T *)0));
924e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return true;
925e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
926e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
927e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        /**
928e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * Moves an object into this container. If it was successful, returns true. Otherwise,
929e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * (e.g. it could not destroy the already stored object) it returns false. This latter
930e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * would be highly unexpected.
931e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
932e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param T type of object to store
933e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \param data object to store
934e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         *
935e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         * \return true if the object was stored. false if it was not.
936e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar         */
937e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        template<
938e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename T,
939e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                typename=is_supported_by_flagger<T>>
940e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        bool set(T &&data) {
941e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            using B = typename Flagger::template store<T>::as_type;
942e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
943e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            // if already contains an object of this type, simply assign
944e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            if (this->flags() == Flagger::flagFor((T*)0) && std::is_same<T, B>::value) {
945e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                _AData_mover<B>::assign(&this->get().template get<B>(), std::forward<T&&>(data));
946e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                return true;
947e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            } else if (this->used()) {
948e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                // destroy previous object
949e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                if (!this->clear()) {
950e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                    return false;
951e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar                }
952e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            }
953e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            this->get().template emplace<B>(std::forward<T&&>(data));
954e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            this->setFlags(Flagger::flagFor((T *)0));
955e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar            return true;
956e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar        }
957e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    };
958e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
959e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
960e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Basic AData using the default type flagger and requested flag type.
961e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
962e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param Flag desired flag type to use. Must be an unsigned and std::integral type.
963e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
964e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Flag>
965e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    using Strict = Custom<flagger<Flag>>;
966e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
967e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
968e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Basic AData using the default type flagger and uint32_t flag.
969e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
970e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    using Basic = Strict<uint32_t>;
971e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
972e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
973e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * AData using the relaxed type flagger for max size and requested flag type.
974e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     *
975e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * \param Flag desired flag type to use. Must be an unsigned and std::integral type.
976e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
977e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    template<typename Flag, size_t MaxSize = 1024, size_t Align = 4>
978e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    using Relaxed = Custom<relaxed_flagger<Flag, MaxSize, Align>>;
979e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
980e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    /**
981e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     * Basic AData using the relaxed type flagger and uint32_t flag.
982e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar     */
983e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar    using RelaxedBasic = Relaxed<uint32_t>;
984e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar};
985e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
986e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar}  // namespace android
987e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
988e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar#endif  // STAGEFRIGHT_FOUNDATION_A_DATA_H_
989e322cc51459b3fac11e7a080c3eb8ee1bfb36fc8Lajos Molnar
990