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