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