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