1*89c4ff92SAndroid Build Coastguard Worker //
2*89c4ff92SAndroid Build Coastguard Worker // Copyright © 2022 Arm Ltd. All rights reserved.
3*89c4ff92SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
4*89c4ff92SAndroid Build Coastguard Worker //
5*89c4ff92SAndroid Build Coastguard Worker #pragma once
6*89c4ff92SAndroid Build Coastguard Worker
7*89c4ff92SAndroid Build Coastguard Worker #include "ProfilingException.hpp"
8*89c4ff92SAndroid Build Coastguard Worker
9*89c4ff92SAndroid Build Coastguard Worker #include <cstring>
10*89c4ff92SAndroid Build Coastguard Worker #include <type_traits>
11*89c4ff92SAndroid Build Coastguard Worker
12*89c4ff92SAndroid Build Coastguard Worker /// Optional is a drop in replacement for std::optional until we migrate
13*89c4ff92SAndroid Build Coastguard Worker /// to c++-17. Only a subset of the optional features are implemented that
14*89c4ff92SAndroid Build Coastguard Worker /// we intend to use in ArmNN.
15*89c4ff92SAndroid Build Coastguard Worker
16*89c4ff92SAndroid Build Coastguard Worker /// There are two distinct implementations here:
17*89c4ff92SAndroid Build Coastguard Worker ///
18*89c4ff92SAndroid Build Coastguard Worker /// 1, for normal constructable/destructable types and reference types
19*89c4ff92SAndroid Build Coastguard Worker /// 2, for reference types
20*89c4ff92SAndroid Build Coastguard Worker
21*89c4ff92SAndroid Build Coastguard Worker /// The std::optional features we support are:
22*89c4ff92SAndroid Build Coastguard Worker ///
23*89c4ff92SAndroid Build Coastguard Worker /// - has_value() and operator bool() to tell if the optional has a value
24*89c4ff92SAndroid Build Coastguard Worker /// - value() returns a reference to the held object
25*89c4ff92SAndroid Build Coastguard Worker ///
26*89c4ff92SAndroid Build Coastguard Worker
27*89c4ff92SAndroid Build Coastguard Worker namespace arm
28*89c4ff92SAndroid Build Coastguard Worker {
29*89c4ff92SAndroid Build Coastguard Worker
30*89c4ff92SAndroid Build Coastguard Worker namespace pipe
31*89c4ff92SAndroid Build Coastguard Worker {
32*89c4ff92SAndroid Build Coastguard Worker
33*89c4ff92SAndroid Build Coastguard Worker /// EmptyOptional is used to initialize the Optional class in case we want
34*89c4ff92SAndroid Build Coastguard Worker /// to have default value for an Optional in a function declaration.
35*89c4ff92SAndroid Build Coastguard Worker struct EmptyOptional {};
36*89c4ff92SAndroid Build Coastguard Worker
37*89c4ff92SAndroid Build Coastguard Worker /// Disambiguation tag that can be passed to the constructor to indicate that
38*89c4ff92SAndroid Build Coastguard Worker /// the contained object should be constructed in-place
39*89c4ff92SAndroid Build Coastguard Worker struct ConstructInPlace
40*89c4ff92SAndroid Build Coastguard Worker {
41*89c4ff92SAndroid Build Coastguard Worker explicit ConstructInPlace() = default;
42*89c4ff92SAndroid Build Coastguard Worker };
43*89c4ff92SAndroid Build Coastguard Worker
44*89c4ff92SAndroid Build Coastguard Worker #define ARM_PIPE_CONSTRUCT_IN_PLACE arm::pipe::ConstructInPlace{}
45*89c4ff92SAndroid Build Coastguard Worker
46*89c4ff92SAndroid Build Coastguard Worker /// OptionalBase is the common functionality between reference and non-reference
47*89c4ff92SAndroid Build Coastguard Worker /// optional types.
48*89c4ff92SAndroid Build Coastguard Worker class OptionalBase
49*89c4ff92SAndroid Build Coastguard Worker {
50*89c4ff92SAndroid Build Coastguard Worker public:
OptionalBase()51*89c4ff92SAndroid Build Coastguard Worker OptionalBase() noexcept
52*89c4ff92SAndroid Build Coastguard Worker : m_HasValue{false}
53*89c4ff92SAndroid Build Coastguard Worker {
54*89c4ff92SAndroid Build Coastguard Worker }
55*89c4ff92SAndroid Build Coastguard Worker
has_value() const56*89c4ff92SAndroid Build Coastguard Worker bool has_value() const noexcept
57*89c4ff92SAndroid Build Coastguard Worker {
58*89c4ff92SAndroid Build Coastguard Worker return m_HasValue;
59*89c4ff92SAndroid Build Coastguard Worker }
60*89c4ff92SAndroid Build Coastguard Worker
61*89c4ff92SAndroid Build Coastguard Worker /// Conversion to bool, so can be used in if-statements and similar contexts expecting a bool.
62*89c4ff92SAndroid Build Coastguard Worker /// Note this is explicit so that it doesn't get implicitly converted to a bool in unwanted cases,
63*89c4ff92SAndroid Build Coastguard Worker /// for example "Optional<TypeA> == Optional<TypeB>" should not compile.
operator bool() const64*89c4ff92SAndroid Build Coastguard Worker explicit operator bool() const noexcept
65*89c4ff92SAndroid Build Coastguard Worker {
66*89c4ff92SAndroid Build Coastguard Worker return has_value();
67*89c4ff92SAndroid Build Coastguard Worker }
68*89c4ff92SAndroid Build Coastguard Worker
69*89c4ff92SAndroid Build Coastguard Worker protected:
OptionalBase(bool hasValue)70*89c4ff92SAndroid Build Coastguard Worker OptionalBase(bool hasValue) noexcept
71*89c4ff92SAndroid Build Coastguard Worker : m_HasValue{hasValue}
72*89c4ff92SAndroid Build Coastguard Worker {
73*89c4ff92SAndroid Build Coastguard Worker }
74*89c4ff92SAndroid Build Coastguard Worker
75*89c4ff92SAndroid Build Coastguard Worker bool m_HasValue;
76*89c4ff92SAndroid Build Coastguard Worker };
77*89c4ff92SAndroid Build Coastguard Worker
78*89c4ff92SAndroid Build Coastguard Worker ///
79*89c4ff92SAndroid Build Coastguard Worker /// The default implementation is the non-reference case. This
80*89c4ff92SAndroid Build Coastguard Worker /// has an unsigned char array for storing the optional value which
81*89c4ff92SAndroid Build Coastguard Worker /// is in-place constructed there.
82*89c4ff92SAndroid Build Coastguard Worker ///
83*89c4ff92SAndroid Build Coastguard Worker template <bool IsReference, typename T>
84*89c4ff92SAndroid Build Coastguard Worker class OptionalReferenceSwitch : public OptionalBase
85*89c4ff92SAndroid Build Coastguard Worker {
86*89c4ff92SAndroid Build Coastguard Worker public:
87*89c4ff92SAndroid Build Coastguard Worker using Base = OptionalBase;
88*89c4ff92SAndroid Build Coastguard Worker
OptionalReferenceSwitch()89*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch() noexcept : Base{} {}
OptionalReferenceSwitch(EmptyOptional)90*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch(EmptyOptional) noexcept : Base{} {}
91*89c4ff92SAndroid Build Coastguard Worker
OptionalReferenceSwitch(const T & value)92*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch(const T& value)
93*89c4ff92SAndroid Build Coastguard Worker : Base{}
94*89c4ff92SAndroid Build Coastguard Worker {
95*89c4ff92SAndroid Build Coastguard Worker Construct(value);
96*89c4ff92SAndroid Build Coastguard Worker }
97*89c4ff92SAndroid Build Coastguard Worker
98*89c4ff92SAndroid Build Coastguard Worker template<class... Args>
OptionalReferenceSwitch(ConstructInPlace,Args &&...args)99*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch(ConstructInPlace, Args&&... args)
100*89c4ff92SAndroid Build Coastguard Worker : Base{}
101*89c4ff92SAndroid Build Coastguard Worker {
102*89c4ff92SAndroid Build Coastguard Worker Construct(ARM_PIPE_CONSTRUCT_IN_PLACE, std::forward<Args>(args)...);
103*89c4ff92SAndroid Build Coastguard Worker }
104*89c4ff92SAndroid Build Coastguard Worker
OptionalReferenceSwitch(const OptionalReferenceSwitch & other)105*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch(const OptionalReferenceSwitch& other)
106*89c4ff92SAndroid Build Coastguard Worker : Base{}
107*89c4ff92SAndroid Build Coastguard Worker {
108*89c4ff92SAndroid Build Coastguard Worker *this = other;
109*89c4ff92SAndroid Build Coastguard Worker }
110*89c4ff92SAndroid Build Coastguard Worker
operator =(const T & value)111*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch& operator=(const T& value)
112*89c4ff92SAndroid Build Coastguard Worker {
113*89c4ff92SAndroid Build Coastguard Worker reset();
114*89c4ff92SAndroid Build Coastguard Worker Construct(value);
115*89c4ff92SAndroid Build Coastguard Worker return *this;
116*89c4ff92SAndroid Build Coastguard Worker }
117*89c4ff92SAndroid Build Coastguard Worker
operator =(const OptionalReferenceSwitch & other)118*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch& operator=(const OptionalReferenceSwitch& other)
119*89c4ff92SAndroid Build Coastguard Worker {
120*89c4ff92SAndroid Build Coastguard Worker reset();
121*89c4ff92SAndroid Build Coastguard Worker if (other.has_value())
122*89c4ff92SAndroid Build Coastguard Worker {
123*89c4ff92SAndroid Build Coastguard Worker Construct(other.value());
124*89c4ff92SAndroid Build Coastguard Worker }
125*89c4ff92SAndroid Build Coastguard Worker
126*89c4ff92SAndroid Build Coastguard Worker return *this;
127*89c4ff92SAndroid Build Coastguard Worker }
128*89c4ff92SAndroid Build Coastguard Worker
operator =(EmptyOptional)129*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch& operator=(EmptyOptional)
130*89c4ff92SAndroid Build Coastguard Worker {
131*89c4ff92SAndroid Build Coastguard Worker reset();
132*89c4ff92SAndroid Build Coastguard Worker return *this;
133*89c4ff92SAndroid Build Coastguard Worker }
134*89c4ff92SAndroid Build Coastguard Worker
~OptionalReferenceSwitch()135*89c4ff92SAndroid Build Coastguard Worker ~OptionalReferenceSwitch()
136*89c4ff92SAndroid Build Coastguard Worker {
137*89c4ff92SAndroid Build Coastguard Worker reset();
138*89c4ff92SAndroid Build Coastguard Worker }
139*89c4ff92SAndroid Build Coastguard Worker
reset()140*89c4ff92SAndroid Build Coastguard Worker void reset()
141*89c4ff92SAndroid Build Coastguard Worker {
142*89c4ff92SAndroid Build Coastguard Worker if (Base::has_value())
143*89c4ff92SAndroid Build Coastguard Worker {
144*89c4ff92SAndroid Build Coastguard Worker value().T::~T();
145*89c4ff92SAndroid Build Coastguard Worker Base::m_HasValue = false;
146*89c4ff92SAndroid Build Coastguard Worker }
147*89c4ff92SAndroid Build Coastguard Worker }
148*89c4ff92SAndroid Build Coastguard Worker
value() const149*89c4ff92SAndroid Build Coastguard Worker const T& value() const
150*89c4ff92SAndroid Build Coastguard Worker {
151*89c4ff92SAndroid Build Coastguard Worker if (!Base::has_value())
152*89c4ff92SAndroid Build Coastguard Worker {
153*89c4ff92SAndroid Build Coastguard Worker throw BadOptionalAccessException("Optional has no value");
154*89c4ff92SAndroid Build Coastguard Worker }
155*89c4ff92SAndroid Build Coastguard Worker
156*89c4ff92SAndroid Build Coastguard Worker auto valuePtr = reinterpret_cast<const T*>(m_Storage);
157*89c4ff92SAndroid Build Coastguard Worker return *valuePtr;
158*89c4ff92SAndroid Build Coastguard Worker }
159*89c4ff92SAndroid Build Coastguard Worker
value()160*89c4ff92SAndroid Build Coastguard Worker T& value()
161*89c4ff92SAndroid Build Coastguard Worker {
162*89c4ff92SAndroid Build Coastguard Worker if (!Base::has_value())
163*89c4ff92SAndroid Build Coastguard Worker {
164*89c4ff92SAndroid Build Coastguard Worker throw BadOptionalAccessException("Optional has no value");
165*89c4ff92SAndroid Build Coastguard Worker }
166*89c4ff92SAndroid Build Coastguard Worker
167*89c4ff92SAndroid Build Coastguard Worker auto valuePtr = reinterpret_cast<T*>(m_Storage);
168*89c4ff92SAndroid Build Coastguard Worker return *valuePtr;
169*89c4ff92SAndroid Build Coastguard Worker }
170*89c4ff92SAndroid Build Coastguard Worker
171*89c4ff92SAndroid Build Coastguard Worker private:
Construct(const T & value)172*89c4ff92SAndroid Build Coastguard Worker void Construct(const T& value)
173*89c4ff92SAndroid Build Coastguard Worker {
174*89c4ff92SAndroid Build Coastguard Worker new (m_Storage) T(value);
175*89c4ff92SAndroid Build Coastguard Worker m_HasValue = true;
176*89c4ff92SAndroid Build Coastguard Worker }
177*89c4ff92SAndroid Build Coastguard Worker
178*89c4ff92SAndroid Build Coastguard Worker template<class... Args>
Construct(ConstructInPlace,Args &&...args)179*89c4ff92SAndroid Build Coastguard Worker void Construct(ConstructInPlace, Args&&... args)
180*89c4ff92SAndroid Build Coastguard Worker {
181*89c4ff92SAndroid Build Coastguard Worker new (m_Storage) T(std::forward<Args>(args)...);
182*89c4ff92SAndroid Build Coastguard Worker m_HasValue = true;
183*89c4ff92SAndroid Build Coastguard Worker }
184*89c4ff92SAndroid Build Coastguard Worker
185*89c4ff92SAndroid Build Coastguard Worker alignas(alignof(T)) unsigned char m_Storage[sizeof(T)];
186*89c4ff92SAndroid Build Coastguard Worker };
187*89c4ff92SAndroid Build Coastguard Worker
188*89c4ff92SAndroid Build Coastguard Worker ///
189*89c4ff92SAndroid Build Coastguard Worker /// This is the special case for reference types. This holds a pointer
190*89c4ff92SAndroid Build Coastguard Worker /// to the referenced type. This doesn't own the referenced memory and
191*89c4ff92SAndroid Build Coastguard Worker /// it never calls delete on the pointer.
192*89c4ff92SAndroid Build Coastguard Worker ///
193*89c4ff92SAndroid Build Coastguard Worker template <typename T>
194*89c4ff92SAndroid Build Coastguard Worker class OptionalReferenceSwitch<true, T> : public OptionalBase
195*89c4ff92SAndroid Build Coastguard Worker {
196*89c4ff92SAndroid Build Coastguard Worker public:
197*89c4ff92SAndroid Build Coastguard Worker using Base = OptionalBase;
198*89c4ff92SAndroid Build Coastguard Worker using NonRefT = typename std::remove_reference<T>::type;
199*89c4ff92SAndroid Build Coastguard Worker
OptionalReferenceSwitch()200*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch() noexcept : Base{}, m_Storage{nullptr} {}
OptionalReferenceSwitch(EmptyOptional)201*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch(EmptyOptional) noexcept : Base{}, m_Storage{nullptr} {}
202*89c4ff92SAndroid Build Coastguard Worker
OptionalReferenceSwitch(const OptionalReferenceSwitch & other)203*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch(const OptionalReferenceSwitch& other) : Base{}
204*89c4ff92SAndroid Build Coastguard Worker {
205*89c4ff92SAndroid Build Coastguard Worker *this = other;
206*89c4ff92SAndroid Build Coastguard Worker }
207*89c4ff92SAndroid Build Coastguard Worker
OptionalReferenceSwitch(T value)208*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch(T value)
209*89c4ff92SAndroid Build Coastguard Worker : Base{true}
210*89c4ff92SAndroid Build Coastguard Worker , m_Storage{&value}
211*89c4ff92SAndroid Build Coastguard Worker {
212*89c4ff92SAndroid Build Coastguard Worker }
213*89c4ff92SAndroid Build Coastguard Worker
214*89c4ff92SAndroid Build Coastguard Worker template<class... Args>
215*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch(ConstructInPlace, Args&&... args) = delete;
216*89c4ff92SAndroid Build Coastguard Worker
operator =(const T value)217*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch& operator=(const T value)
218*89c4ff92SAndroid Build Coastguard Worker {
219*89c4ff92SAndroid Build Coastguard Worker m_Storage = &value;
220*89c4ff92SAndroid Build Coastguard Worker Base::m_HasValue = true;
221*89c4ff92SAndroid Build Coastguard Worker return *this;
222*89c4ff92SAndroid Build Coastguard Worker }
223*89c4ff92SAndroid Build Coastguard Worker
operator =(const OptionalReferenceSwitch & other)224*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch& operator=(const OptionalReferenceSwitch& other)
225*89c4ff92SAndroid Build Coastguard Worker {
226*89c4ff92SAndroid Build Coastguard Worker m_Storage = other.m_Storage;
227*89c4ff92SAndroid Build Coastguard Worker Base::m_HasValue = other.has_value();
228*89c4ff92SAndroid Build Coastguard Worker return *this;
229*89c4ff92SAndroid Build Coastguard Worker }
230*89c4ff92SAndroid Build Coastguard Worker
operator =(EmptyOptional)231*89c4ff92SAndroid Build Coastguard Worker OptionalReferenceSwitch& operator=(EmptyOptional)
232*89c4ff92SAndroid Build Coastguard Worker {
233*89c4ff92SAndroid Build Coastguard Worker reset();
234*89c4ff92SAndroid Build Coastguard Worker return *this;
235*89c4ff92SAndroid Build Coastguard Worker }
236*89c4ff92SAndroid Build Coastguard Worker
~OptionalReferenceSwitch()237*89c4ff92SAndroid Build Coastguard Worker ~OptionalReferenceSwitch()
238*89c4ff92SAndroid Build Coastguard Worker {
239*89c4ff92SAndroid Build Coastguard Worker reset();
240*89c4ff92SAndroid Build Coastguard Worker }
241*89c4ff92SAndroid Build Coastguard Worker
reset()242*89c4ff92SAndroid Build Coastguard Worker void reset()
243*89c4ff92SAndroid Build Coastguard Worker {
244*89c4ff92SAndroid Build Coastguard Worker Base::m_HasValue = false;
245*89c4ff92SAndroid Build Coastguard Worker m_Storage = nullptr;
246*89c4ff92SAndroid Build Coastguard Worker }
247*89c4ff92SAndroid Build Coastguard Worker
value() const248*89c4ff92SAndroid Build Coastguard Worker const T value() const
249*89c4ff92SAndroid Build Coastguard Worker {
250*89c4ff92SAndroid Build Coastguard Worker if (!Base::has_value())
251*89c4ff92SAndroid Build Coastguard Worker {
252*89c4ff92SAndroid Build Coastguard Worker throw BadOptionalAccessException("Optional has no value");
253*89c4ff92SAndroid Build Coastguard Worker }
254*89c4ff92SAndroid Build Coastguard Worker
255*89c4ff92SAndroid Build Coastguard Worker return *m_Storage;
256*89c4ff92SAndroid Build Coastguard Worker }
257*89c4ff92SAndroid Build Coastguard Worker
value()258*89c4ff92SAndroid Build Coastguard Worker T value()
259*89c4ff92SAndroid Build Coastguard Worker {
260*89c4ff92SAndroid Build Coastguard Worker if (!Base::has_value())
261*89c4ff92SAndroid Build Coastguard Worker {
262*89c4ff92SAndroid Build Coastguard Worker throw BadOptionalAccessException("Optional has no value");
263*89c4ff92SAndroid Build Coastguard Worker }
264*89c4ff92SAndroid Build Coastguard Worker
265*89c4ff92SAndroid Build Coastguard Worker return *m_Storage;
266*89c4ff92SAndroid Build Coastguard Worker }
267*89c4ff92SAndroid Build Coastguard Worker
268*89c4ff92SAndroid Build Coastguard Worker private:
269*89c4ff92SAndroid Build Coastguard Worker NonRefT* m_Storage;
270*89c4ff92SAndroid Build Coastguard Worker };
271*89c4ff92SAndroid Build Coastguard Worker
272*89c4ff92SAndroid Build Coastguard Worker template <typename T>
273*89c4ff92SAndroid Build Coastguard Worker class Optional final : public OptionalReferenceSwitch<std::is_reference<T>::value, T>
274*89c4ff92SAndroid Build Coastguard Worker {
275*89c4ff92SAndroid Build Coastguard Worker public:
276*89c4ff92SAndroid Build Coastguard Worker using BaseSwitch = OptionalReferenceSwitch<std::is_reference<T>::value, T>;
277*89c4ff92SAndroid Build Coastguard Worker
Optional()278*89c4ff92SAndroid Build Coastguard Worker Optional() noexcept : BaseSwitch{} {}
Optional(const T & value)279*89c4ff92SAndroid Build Coastguard Worker Optional(const T& value) : BaseSwitch{value} {}
280*89c4ff92SAndroid Build Coastguard Worker Optional& operator=(const Optional& other) = default;
Optional(EmptyOptional empty)281*89c4ff92SAndroid Build Coastguard Worker Optional(EmptyOptional empty) : BaseSwitch{empty} {}
Optional(const Optional & other)282*89c4ff92SAndroid Build Coastguard Worker Optional(const Optional& other) : BaseSwitch{other} {}
Optional(const BaseSwitch & other)283*89c4ff92SAndroid Build Coastguard Worker Optional(const BaseSwitch& other) : BaseSwitch{other} {}
284*89c4ff92SAndroid Build Coastguard Worker
285*89c4ff92SAndroid Build Coastguard Worker template<class... Args>
Optional(ConstructInPlace,Args &&...args)286*89c4ff92SAndroid Build Coastguard Worker explicit Optional(ConstructInPlace, Args&&... args) :
287*89c4ff92SAndroid Build Coastguard Worker BaseSwitch(ARM_PIPE_CONSTRUCT_IN_PLACE, std::forward<Args>(args)...) {}
288*89c4ff92SAndroid Build Coastguard Worker
289*89c4ff92SAndroid Build Coastguard Worker /// Two optionals are considered equal if they are both empty or both contain values which
290*89c4ff92SAndroid Build Coastguard Worker /// themselves are considered equal (via their own == operator).
operator ==(const Optional<T> & rhs) const291*89c4ff92SAndroid Build Coastguard Worker bool operator==(const Optional<T>& rhs) const
292*89c4ff92SAndroid Build Coastguard Worker {
293*89c4ff92SAndroid Build Coastguard Worker if (!this->has_value() && !rhs.has_value())
294*89c4ff92SAndroid Build Coastguard Worker {
295*89c4ff92SAndroid Build Coastguard Worker return true;
296*89c4ff92SAndroid Build Coastguard Worker }
297*89c4ff92SAndroid Build Coastguard Worker if (this->has_value() && rhs.has_value() && this->value() == rhs.value())
298*89c4ff92SAndroid Build Coastguard Worker {
299*89c4ff92SAndroid Build Coastguard Worker return true;
300*89c4ff92SAndroid Build Coastguard Worker }
301*89c4ff92SAndroid Build Coastguard Worker return false;
302*89c4ff92SAndroid Build Coastguard Worker }
303*89c4ff92SAndroid Build Coastguard Worker };
304*89c4ff92SAndroid Build Coastguard Worker
305*89c4ff92SAndroid Build Coastguard Worker /// Utility template that constructs an object of type T in-place and wraps
306*89c4ff92SAndroid Build Coastguard Worker /// it inside an Optional<T> object
307*89c4ff92SAndroid Build Coastguard Worker template<typename T, class... Args>
MakeOptional(Args &&...args)308*89c4ff92SAndroid Build Coastguard Worker Optional<T> MakeOptional(Args&&... args)
309*89c4ff92SAndroid Build Coastguard Worker {
310*89c4ff92SAndroid Build Coastguard Worker return Optional<T>(ARM_PIPE_CONSTRUCT_IN_PLACE, std::forward<Args>(args)...);
311*89c4ff92SAndroid Build Coastguard Worker }
312*89c4ff92SAndroid Build Coastguard Worker
313*89c4ff92SAndroid Build Coastguard Worker } // namespace pipe
314*89c4ff92SAndroid Build Coastguard Worker } // namespace arm
315