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