boxed_value.h revision 02f7c1dee242f490143791dbb73fa23fa3007cfa
1// Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef UPDATE_ENGINE_UPDATE_MANAGER_BOXED_VALUE_H_ 6#define UPDATE_ENGINE_UPDATE_MANAGER_BOXED_VALUE_H_ 7 8#include <memory> 9#include <string> 10 11#include <base/macros.h> 12 13namespace chromeos_update_manager { 14 15// BoxedValue is a class to hold pointers of a given type that deletes them when 16// the instance goes out of scope, as std::unique_ptr<T> does. The main 17// difference with it is that the type T is not part of the class, i.e., this 18// isn't a parametric class. The class has a parametric constructor that accepts 19// a const T* which will define the type of the object passed on delete. 20// 21// It is safe to use this class in linked containers such as std::list and 22// std::map but the object can't be copied. This means that you need to 23// construct the BoxedValue in place using a container method like emplace() 24// or move it with std::move(). 25// 26// list<BoxedValue> lst; 27// lst.emplace_back(new const int(42)); 28// lst.emplace_back(new const string("Hello world!")); 29// 30// map<int, BoxedValue> m; 31// m.emplace(123, std::move(BoxedValue(new const string("Hola mundo!")))); 32// 33// auto it = m.find(42); 34// if (it != m.end()) 35// cout << "m[42] points to " << it->second.value() << endl; 36// cout << "m[33] points to " << m[33].value() << endl; 37// 38// Since copy and assign are not allowed, you can't create a copy of the 39// BoxedValue which means that you can only use a reference to it. 40// 41 42class BoxedValue { 43 public: 44 // Creates an empty BoxedValue. Since the pointer can't be assigned from other 45 // BoxedValues or pointers, this is only useful in places where a default 46 // constructor is required, such as std::map::operator[]. 47 BoxedValue() : value_(nullptr), deleter_(nullptr), printer_(nullptr) {} 48 49 // Creates a BoxedValue for the passed pointer |value|. The BoxedValue keeps 50 // the ownership of this pointer and can't be released. 51 template<typename T> 52 explicit BoxedValue(const T* value) 53 : value_(static_cast<const void*>(value)), deleter_(ValueDeleter<T>), 54 printer_(ValuePrinter<T>) {} 55 56 // The move constructor takes ownership of the pointer since the semantics of 57 // it allows to render the passed BoxedValue undefined. You need to use the 58 // move constructor explicitly preventing it from accidental references, 59 // like in: 60 // BoxedValue new_box(std::move(other_box)); 61 BoxedValue(BoxedValue&& other) // NOLINT(build/c++11) 62 : value_(other.value_), deleter_(other.deleter_), 63 printer_(other.printer_) { 64 other.value_ = nullptr; 65 other.deleter_ = nullptr; 66 other.printer_ = nullptr; 67 } 68 69 // Deletes the |value| passed on construction using the delete for the passed 70 // type. 71 ~BoxedValue() { 72 if (deleter_) 73 deleter_(value_); 74 } 75 76 const void* value() const { return value_; } 77 78 std::string ToString() const { 79 if (!printer_) 80 return "(no printer)"; 81 if (!value_) 82 return "(no value)"; 83 return printer_(value_); 84 } 85 86 // Static method to call the destructor of the right type. 87 template<typename T> 88 static void ValueDeleter(const void* value) { 89 delete reinterpret_cast<const T*>(value); 90 } 91 92 // Static method to print a type. See boxed_value.cc for common 93 // instantiations. 94 template<typename T> 95 static std::string ValuePrinter(const void* value); 96 97 private: 98 // A pointer to the cached value. 99 const void* value_; 100 101 // A function that calls delete for the right type of value_. 102 void (*deleter_)(const void*); 103 104 // A function that converts value_ to a string. 105 std::string (*printer_)(const void*); 106 107 DISALLOW_COPY_AND_ASSIGN(BoxedValue); 108}; 109 110} // namespace chromeos_update_manager 111 112#endif // UPDATE_ENGINE_UPDATE_MANAGER_BOXED_VALUE_H_ 113