1 /*
2 * \brief Utility for the manual placement of objects
3 * \author Norman Feske
4 * \date 2014-02-07
5 */
6
7 /*
8 * Copyright (C) 2014 Genode Labs GmbH
9 *
10 * This file is part of the Genode OS framework, which is distributed
11 * under the terms of the GNU General Public License version 2.
12 */
13
14 #ifndef _INCLUDE__UTIL__CONSTRUCT_AT_H_
15 #define _INCLUDE__UTIL__CONSTRUCT_AT_H_
16
17 #include <base/stdint.h>
18 #include <base/printf.h>
19
20 namespace Genode {
21
22 template <typename T, typename... ARGS>
23 static inline T *construct_at(void *, ARGS &&...);
24 }
25
26
27 /**
28 * Construct object of given type at a specific location
29 *
30 * \param T object type
31 * \param at desired object location
32 * \param args list of arguments for the object constructor
33 *
34 * \return typed object pointer
35 *
36 * We use move semantics (ARGS &&) because otherwise the compiler would create
37 * a temporary copy of all arguments that have a reference type and use a
38 * reference to this copy instead of the original within this function.
39 *
40 * There is a slight difference between the object that is constructed by this
41 * function and a common object of the given type. If the destructor of the
42 * given type or of any base of the given type is virtual, the vtable of the
43 * returned object references an empty delete(void *) operator for that
44 * destructor. However, this shouldn`t be a problem as an object constructed by
45 * this function should never get destructed implicitely or through a delete
46 * expression.
47 */
48 template <typename T, typename... ARGS>
49 static inline T * Genode::construct_at(void *at, ARGS &&... args)
50 {
51 /**
52 * Utility to equip an existing type `T` with a placement new operator
53 */
54 struct Placeable : T
55 {
56 Placeable(ARGS &&... args) : T(args...) { }
57
58 void * operator new (size_t, void *ptr) { return ptr; }
59 void operator delete (void *, void *) { }
60
61 /**
62 * Standard delete operator
63 *
64 * As we explicitely define one version of the delete operator, the
65 * compiler won`t implicitely define any delete version for this class.
66 * But if type T has a virtual destructor, the compiler implicitely
67 * defines a `virtual ~Placeable()` which needs the following operator.
68 */
69 void operator delete (void *)
70 {
71 PERR("cxx: Placeable::operator delete (void *) not supported.");
72 }
73 };
74
75 /*
76 * If the args input to this function contains rvalues, the compiler would
77 * use the according rvalue references as lvalues at the following call if
78 * we don`t cast them back to rvalue references explicitely. We can not use
79 * lvalues here because the compiler can not bind them to rvalue references
80 * as expected by Placeable.
81 */
82 return new (at) Placeable(static_cast<ARGS &&>(args)...);
83 }
84
85 #endif /* _INCLUDE__UTIL__CONSTRUCT_AT_H_ */