annotate win32-mingw/include/kj/common.h @ 146:206f0eb279b8

Remove "other" Vamp SDK repo from sv-dependency-builds
author Chris Cannam <cannam@all-day-breakfast.com>
date Mon, 06 Mar 2017 13:29:58 +0000
parents 38d1c0e7850b
children eccd51b72864
rev   line source
cannam@135 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
cannam@135 2 // Licensed under the MIT License:
cannam@135 3 //
cannam@135 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
cannam@135 5 // of this software and associated documentation files (the "Software"), to deal
cannam@135 6 // in the Software without restriction, including without limitation the rights
cannam@135 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
cannam@135 8 // copies of the Software, and to permit persons to whom the Software is
cannam@135 9 // furnished to do so, subject to the following conditions:
cannam@135 10 //
cannam@135 11 // The above copyright notice and this permission notice shall be included in
cannam@135 12 // all copies or substantial portions of the Software.
cannam@135 13 //
cannam@135 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
cannam@135 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
cannam@135 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
cannam@135 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
cannam@135 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
cannam@135 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
cannam@135 20 // THE SOFTWARE.
cannam@135 21
cannam@135 22 // Header that should be #included by everyone.
cannam@135 23 //
cannam@135 24 // This defines very simple utilities that are widely applicable.
cannam@135 25
cannam@135 26 #ifndef KJ_COMMON_H_
cannam@135 27 #define KJ_COMMON_H_
cannam@135 28
cannam@135 29 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS
cannam@135 30 #pragma GCC system_header
cannam@135 31 #endif
cannam@135 32
cannam@135 33 #ifndef KJ_NO_COMPILER_CHECK
cannam@135 34 #if __cplusplus < 201103L && !__CDT_PARSER__ && !_MSC_VER
cannam@135 35 #error "This code requires C++11. Either your compiler does not support it or it is not enabled."
cannam@135 36 #ifdef __GNUC__
cannam@135 37 // Compiler claims compatibility with GCC, so presumably supports -std.
cannam@135 38 #error "Pass -std=c++11 on the compiler command line to enable C++11."
cannam@135 39 #endif
cannam@135 40 #endif
cannam@135 41
cannam@135 42 #ifdef __GNUC__
cannam@135 43 #if __clang__
cannam@135 44 #if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2)
cannam@135 45 #warning "This library requires at least Clang 3.2."
cannam@135 46 #elif defined(__apple_build_version__) && __apple_build_version__ <= 4250028
cannam@135 47 #warning "This library requires at least Clang 3.2. XCode 4.6's Clang, which claims to be "\
cannam@135 48 "version 4.2 (wat?), is actually built from some random SVN revision between 3.1 "\
cannam@135 49 "and 3.2. Unfortunately, it is insufficient for compiling this library. You can "\
cannam@135 50 "download the real Clang 3.2 (or newer) from the Clang web site. Step-by-step "\
cannam@135 51 "instructions can be found in Cap'n Proto's documentation: "\
cannam@135 52 "http://kentonv.github.io/capnproto/install.html#clang_32_on_mac_osx"
cannam@135 53 #elif __cplusplus >= 201103L && !__has_include(<initializer_list>)
cannam@135 54 #warning "Your compiler supports C++11 but your C++ standard library does not. If your "\
cannam@135 55 "system has libc++ installed (as should be the case on e.g. Mac OSX), try adding "\
cannam@135 56 "-stdlib=libc++ to your CXXFLAGS."
cannam@135 57 #endif
cannam@135 58 #else
cannam@135 59 #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7)
cannam@135 60 #warning "This library requires at least GCC 4.7."
cannam@135 61 #endif
cannam@135 62 #endif
cannam@135 63 #elif defined(_MSC_VER)
cannam@135 64 #if _MSC_VER < 1900
cannam@135 65 #error "You need Visual Studio 2015 or better to compile this code."
cannam@135 66 #elif !CAPNP_LITE
cannam@135 67 // TODO(cleanup): This is KJ, but we're talking about Cap'n Proto.
cannam@135 68 #error "As of this writing, Cap'n Proto only supports Visual C++ in 'lite mode'; please #define CAPNP_LITE"
cannam@135 69 #endif
cannam@135 70 #else
cannam@135 71 #warning "I don't recognize your compiler. As of this writing, Clang and GCC are the only "\
cannam@135 72 "known compilers with enough C++11 support for this library. "\
cannam@135 73 "#define KJ_NO_COMPILER_CHECK to make this warning go away."
cannam@135 74 #endif
cannam@135 75 #endif
cannam@135 76
cannam@135 77 #include <stddef.h>
cannam@135 78 #include <initializer_list>
cannam@135 79
cannam@135 80 #if __linux__ && __cplusplus > 201200L
cannam@135 81 // Hack around stdlib bug with C++14 that exists on some Linux systems.
cannam@135 82 // Apparently in this mode the C library decides not to define gets() but the C++ library still
cannam@135 83 // tries to import it into the std namespace. This bug has been fixed at the source but is still
cannam@135 84 // widely present in the wild e.g. on Ubuntu 14.04.
cannam@135 85 #undef _GLIBCXX_HAVE_GETS
cannam@135 86 #endif
cannam@135 87
cannam@135 88 #if defined(_MSC_VER)
cannam@135 89 #include <intrin.h> // __popcnt
cannam@135 90 #endif
cannam@135 91
cannam@135 92 // =======================================================================================
cannam@135 93
cannam@135 94 namespace kj {
cannam@135 95
cannam@135 96 typedef unsigned int uint;
cannam@135 97 typedef unsigned char byte;
cannam@135 98
cannam@135 99 // =======================================================================================
cannam@135 100 // Common macros, especially for common yet compiler-specific features.
cannam@135 101
cannam@135 102 // Detect whether RTTI and exceptions are enabled, assuming they are unless we have specific
cannam@135 103 // evidence to the contrary. Clients can always define KJ_NO_RTTI or KJ_NO_EXCEPTIONS explicitly
cannam@135 104 // to override these checks.
cannam@135 105 #ifdef __GNUC__
cannam@135 106 #if !defined(KJ_NO_RTTI) && !__GXX_RTTI
cannam@135 107 #define KJ_NO_RTTI 1
cannam@135 108 #endif
cannam@135 109 #if !defined(KJ_NO_EXCEPTIONS) && !__EXCEPTIONS
cannam@135 110 #define KJ_NO_EXCEPTIONS 1
cannam@135 111 #endif
cannam@135 112 #elif defined(_MSC_VER)
cannam@135 113 #if !defined(KJ_NO_RTTI) && !defined(_CPPRTTI)
cannam@135 114 #define KJ_NO_RTTI 1
cannam@135 115 #endif
cannam@135 116 #if !defined(KJ_NO_EXCEPTIONS) && !defined(_CPPUNWIND)
cannam@135 117 #define KJ_NO_EXCEPTIONS 1
cannam@135 118 #endif
cannam@135 119 #endif
cannam@135 120
cannam@135 121 #if !defined(KJ_DEBUG) && !defined(KJ_NDEBUG)
cannam@135 122 // Heuristically decide whether to enable debug mode. If DEBUG or NDEBUG is defined, use that.
cannam@135 123 // Otherwise, fall back to checking whether optimization is enabled.
cannam@135 124 #if defined(DEBUG) || defined(_DEBUG)
cannam@135 125 #define KJ_DEBUG
cannam@135 126 #elif defined(NDEBUG)
cannam@135 127 #define KJ_NDEBUG
cannam@135 128 #elif __OPTIMIZE__
cannam@135 129 #define KJ_NDEBUG
cannam@135 130 #else
cannam@135 131 #define KJ_DEBUG
cannam@135 132 #endif
cannam@135 133 #endif
cannam@135 134
cannam@135 135 #define KJ_DISALLOW_COPY(classname) \
cannam@135 136 classname(const classname&) = delete; \
cannam@135 137 classname& operator=(const classname&) = delete
cannam@135 138 // Deletes the implicit copy constructor and assignment operator.
cannam@135 139
cannam@135 140 #ifdef __GNUC__
cannam@135 141 #define KJ_LIKELY(condition) __builtin_expect(condition, true)
cannam@135 142 #define KJ_UNLIKELY(condition) __builtin_expect(condition, false)
cannam@135 143 // Branch prediction macros. Evaluates to the condition given, but also tells the compiler that we
cannam@135 144 // expect the condition to be true/false enough of the time that it's worth hard-coding branch
cannam@135 145 // prediction.
cannam@135 146 #else
cannam@135 147 #define KJ_LIKELY(condition) (condition)
cannam@135 148 #define KJ_UNLIKELY(condition) (condition)
cannam@135 149 #endif
cannam@135 150
cannam@135 151 #if defined(KJ_DEBUG) || __NO_INLINE__
cannam@135 152 #define KJ_ALWAYS_INLINE(prototype) inline prototype
cannam@135 153 // Don't force inline in debug mode.
cannam@135 154 #else
cannam@135 155 #if defined(_MSC_VER)
cannam@135 156 #define KJ_ALWAYS_INLINE(prototype) __forceinline prototype
cannam@135 157 #else
cannam@135 158 #define KJ_ALWAYS_INLINE(prototype) inline prototype __attribute__((always_inline))
cannam@135 159 #endif
cannam@135 160 // Force a function to always be inlined. Apply only to the prototype, not to the definition.
cannam@135 161 #endif
cannam@135 162
cannam@135 163 #if defined(_MSC_VER)
cannam@135 164 #define KJ_NOINLINE __declspec(noinline)
cannam@135 165 #else
cannam@135 166 #define KJ_NOINLINE __attribute__((noinline))
cannam@135 167 #endif
cannam@135 168
cannam@135 169 #if defined(_MSC_VER)
cannam@135 170 #define KJ_NORETURN(prototype) __declspec(noreturn) prototype
cannam@135 171 #define KJ_UNUSED
cannam@135 172 #define KJ_WARN_UNUSED_RESULT
cannam@135 173 // TODO(msvc): KJ_WARN_UNUSED_RESULT can use _Check_return_ on MSVC, but it's a prefix, so
cannam@135 174 // wrapping the whole prototype is needed. http://msdn.microsoft.com/en-us/library/jj159529.aspx
cannam@135 175 // Similarly, KJ_UNUSED could use __pragma(warning(suppress:...)), but again that's a prefix.
cannam@135 176 #else
cannam@135 177 #define KJ_NORETURN(prototype) prototype __attribute__((noreturn))
cannam@135 178 #define KJ_UNUSED __attribute__((unused))
cannam@135 179 #define KJ_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
cannam@135 180 #endif
cannam@135 181
cannam@135 182 #if __clang__
cannam@135 183 #define KJ_UNUSED_MEMBER __attribute__((unused))
cannam@135 184 // Inhibits "unused" warning for member variables. Only Clang produces such a warning, while GCC
cannam@135 185 // complains if the attribute is set on members.
cannam@135 186 #else
cannam@135 187 #define KJ_UNUSED_MEMBER
cannam@135 188 #endif
cannam@135 189
cannam@135 190 #if __clang__
cannam@135 191 #define KJ_DEPRECATED(reason) \
cannam@135 192 __attribute__((deprecated(reason)))
cannam@135 193 #define KJ_UNAVAILABLE(reason) \
cannam@135 194 __attribute__((unavailable(reason)))
cannam@135 195 #elif __GNUC__
cannam@135 196 #define KJ_DEPRECATED(reason) \
cannam@135 197 __attribute__((deprecated))
cannam@135 198 #define KJ_UNAVAILABLE(reason)
cannam@135 199 #else
cannam@135 200 #define KJ_DEPRECATED(reason)
cannam@135 201 #define KJ_UNAVAILABLE(reason)
cannam@135 202 // TODO(msvc): Again, here, MSVC prefers a prefix, __declspec(deprecated).
cannam@135 203 #endif
cannam@135 204
cannam@135 205 namespace _ { // private
cannam@135 206
cannam@135 207 KJ_NORETURN(void inlineRequireFailure(
cannam@135 208 const char* file, int line, const char* expectation, const char* macroArgs,
cannam@135 209 const char* message = nullptr));
cannam@135 210
cannam@135 211 KJ_NORETURN(void unreachable());
cannam@135 212
cannam@135 213 } // namespace _ (private)
cannam@135 214
cannam@135 215 #ifdef KJ_DEBUG
cannam@135 216 #if _MSC_VER
cannam@135 217 #define KJ_IREQUIRE(condition, ...) \
cannam@135 218 if (KJ_LIKELY(condition)); else ::kj::_::inlineRequireFailure( \
cannam@135 219 __FILE__, __LINE__, #condition, "" #__VA_ARGS__, __VA_ARGS__)
cannam@135 220 // Version of KJ_DREQUIRE() which is safe to use in headers that are #included by users. Used to
cannam@135 221 // check preconditions inside inline methods. KJ_IREQUIRE is particularly useful in that
cannam@135 222 // it will be enabled depending on whether the application is compiled in debug mode rather than
cannam@135 223 // whether libkj is.
cannam@135 224 #else
cannam@135 225 #define KJ_IREQUIRE(condition, ...) \
cannam@135 226 if (KJ_LIKELY(condition)); else ::kj::_::inlineRequireFailure( \
cannam@135 227 __FILE__, __LINE__, #condition, #__VA_ARGS__, ##__VA_ARGS__)
cannam@135 228 // Version of KJ_DREQUIRE() which is safe to use in headers that are #included by users. Used to
cannam@135 229 // check preconditions inside inline methods. KJ_IREQUIRE is particularly useful in that
cannam@135 230 // it will be enabled depending on whether the application is compiled in debug mode rather than
cannam@135 231 // whether libkj is.
cannam@135 232 #endif
cannam@135 233 #else
cannam@135 234 #define KJ_IREQUIRE(condition, ...)
cannam@135 235 #endif
cannam@135 236
cannam@135 237 #define KJ_IASSERT KJ_IREQUIRE
cannam@135 238
cannam@135 239 #define KJ_UNREACHABLE ::kj::_::unreachable();
cannam@135 240 // Put this on code paths that cannot be reached to suppress compiler warnings about missing
cannam@135 241 // returns.
cannam@135 242
cannam@135 243 #if __clang__
cannam@135 244 #define KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT
cannam@135 245 #else
cannam@135 246 #define KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT KJ_UNREACHABLE
cannam@135 247 #endif
cannam@135 248
cannam@135 249 // #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack)
cannam@135 250 //
cannam@135 251 // Allocate an array, preferably on the stack, unless it is too big. On GCC this will use
cannam@135 252 // variable-sized arrays. For other compilers we could just use a fixed-size array. `minStack`
cannam@135 253 // is the stack array size to use if variable-width arrays are not supported. `maxStack` is the
cannam@135 254 // maximum stack array size if variable-width arrays *are* supported.
cannam@135 255 #if __GNUC__ && !__clang__
cannam@135 256 #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack) \
cannam@135 257 size_t name##_size = (size); \
cannam@135 258 bool name##_isOnStack = name##_size <= (maxStack); \
cannam@135 259 type name##_stack[name##_isOnStack ? size : 0]; \
cannam@135 260 ::kj::Array<type> name##_heap = name##_isOnStack ? \
cannam@135 261 nullptr : kj::heapArray<type>(name##_size); \
cannam@135 262 ::kj::ArrayPtr<type> name = name##_isOnStack ? \
cannam@135 263 kj::arrayPtr(name##_stack, name##_size) : name##_heap
cannam@135 264 #else
cannam@135 265 #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack) \
cannam@135 266 size_t name##_size = (size); \
cannam@135 267 bool name##_isOnStack = name##_size <= (minStack); \
cannam@135 268 type name##_stack[minStack]; \
cannam@135 269 ::kj::Array<type> name##_heap = name##_isOnStack ? \
cannam@135 270 nullptr : kj::heapArray<type>(name##_size); \
cannam@135 271 ::kj::ArrayPtr<type> name = name##_isOnStack ? \
cannam@135 272 kj::arrayPtr(name##_stack, name##_size) : name##_heap
cannam@135 273 #endif
cannam@135 274
cannam@135 275 #define KJ_CONCAT_(x, y) x##y
cannam@135 276 #define KJ_CONCAT(x, y) KJ_CONCAT_(x, y)
cannam@135 277 #define KJ_UNIQUE_NAME(prefix) KJ_CONCAT(prefix, __LINE__)
cannam@135 278 // Create a unique identifier name. We use concatenate __LINE__ rather than __COUNTER__ so that
cannam@135 279 // the name can be used multiple times in the same macro.
cannam@135 280
cannam@135 281 #if _MSC_VER
cannam@135 282
cannam@135 283 #define KJ_CONSTEXPR(...) __VA_ARGS__
cannam@135 284 // Use in cases where MSVC barfs on constexpr. A replacement keyword (e.g. "const") can be
cannam@135 285 // provided, or just leave blank to remove the keyword entirely.
cannam@135 286 //
cannam@135 287 // TODO(msvc): Remove this hack once MSVC fully supports constexpr.
cannam@135 288
cannam@135 289 #ifndef __restrict__
cannam@135 290 #define __restrict__ __restrict
cannam@135 291 // TODO(msvc): Would it be better to define a KJ_RESTRICT macro?
cannam@135 292 #endif
cannam@135 293
cannam@135 294 #pragma warning(disable: 4521 4522)
cannam@135 295 // This warning complains when there are two copy constructors, one for a const reference and
cannam@135 296 // one for a non-const reference. It is often quite necessary to do this in wrapper templates,
cannam@135 297 // therefore this warning is dumb and we disable it.
cannam@135 298
cannam@135 299 #pragma warning(disable: 4458)
cannam@135 300 // Warns when a parameter name shadows a class member. Unfortunately my code does this a lot,
cannam@135 301 // since I don't use a special name format for members.
cannam@135 302
cannam@135 303 #else // _MSC_VER
cannam@135 304 #define KJ_CONSTEXPR(...) constexpr
cannam@135 305 #endif
cannam@135 306
cannam@135 307 // =======================================================================================
cannam@135 308 // Template metaprogramming helpers.
cannam@135 309
cannam@135 310 template <typename T> struct NoInfer_ { typedef T Type; };
cannam@135 311 template <typename T> using NoInfer = typename NoInfer_<T>::Type;
cannam@135 312 // Use NoInfer<T>::Type in place of T for a template function parameter to prevent inference of
cannam@135 313 // the type based on the parameter value.
cannam@135 314
cannam@135 315 template <typename T> struct RemoveConst_ { typedef T Type; };
cannam@135 316 template <typename T> struct RemoveConst_<const T> { typedef T Type; };
cannam@135 317 template <typename T> using RemoveConst = typename RemoveConst_<T>::Type;
cannam@135 318
cannam@135 319 template <typename> struct IsLvalueReference_ { static constexpr bool value = false; };
cannam@135 320 template <typename T> struct IsLvalueReference_<T&> { static constexpr bool value = true; };
cannam@135 321 template <typename T>
cannam@135 322 inline constexpr bool isLvalueReference() { return IsLvalueReference_<T>::value; }
cannam@135 323
cannam@135 324 template <typename T> struct Decay_ { typedef T Type; };
cannam@135 325 template <typename T> struct Decay_<T&> { typedef typename Decay_<T>::Type Type; };
cannam@135 326 template <typename T> struct Decay_<T&&> { typedef typename Decay_<T>::Type Type; };
cannam@135 327 template <typename T> struct Decay_<T[]> { typedef typename Decay_<T*>::Type Type; };
cannam@135 328 template <typename T> struct Decay_<const T[]> { typedef typename Decay_<const T*>::Type Type; };
cannam@135 329 template <typename T, size_t s> struct Decay_<T[s]> { typedef typename Decay_<T*>::Type Type; };
cannam@135 330 template <typename T, size_t s> struct Decay_<const T[s]> { typedef typename Decay_<const T*>::Type Type; };
cannam@135 331 template <typename T> struct Decay_<const T> { typedef typename Decay_<T>::Type Type; };
cannam@135 332 template <typename T> struct Decay_<volatile T> { typedef typename Decay_<T>::Type Type; };
cannam@135 333 template <typename T> using Decay = typename Decay_<T>::Type;
cannam@135 334
cannam@135 335 template <bool b> struct EnableIf_;
cannam@135 336 template <> struct EnableIf_<true> { typedef void Type; };
cannam@135 337 template <bool b> using EnableIf = typename EnableIf_<b>::Type;
cannam@135 338 // Use like:
cannam@135 339 //
cannam@135 340 // template <typename T, typename = EnableIf<isValid<T>()>
cannam@135 341 // void func(T&& t);
cannam@135 342
cannam@135 343 template <typename...> struct VoidSfinae_ { using Type = void; };
cannam@135 344 template <typename... Ts> using VoidSfinae = typename VoidSfinae_<Ts...>::Type;
cannam@135 345 // Note: VoidSfinae is std::void_t from C++17.
cannam@135 346
cannam@135 347 template <typename T>
cannam@135 348 T instance() noexcept;
cannam@135 349 // Like std::declval, but doesn't transform T into an rvalue reference. If you want that, specify
cannam@135 350 // instance<T&&>().
cannam@135 351
cannam@135 352 struct DisallowConstCopy {
cannam@135 353 // Inherit from this, or declare a member variable of this type, to prevent the class from being
cannam@135 354 // copyable from a const reference -- instead, it will only be copyable from non-const references.
cannam@135 355 // This is useful for enforcing transitive constness of contained pointers.
cannam@135 356 //
cannam@135 357 // For example, say you have a type T which contains a pointer. T has non-const methods which
cannam@135 358 // modify the value at that pointer, but T's const methods are designed to allow reading only.
cannam@135 359 // Unfortunately, if T has a regular copy constructor, someone can simply make a copy of T and
cannam@135 360 // then use it to modify the pointed-to value. However, if T inherits DisallowConstCopy, then
cannam@135 361 // callers will only be able to copy non-const instances of T. Ideally, there is some
cannam@135 362 // parallel type ImmutableT which is like a version of T that only has const methods, and can
cannam@135 363 // be copied from a const T.
cannam@135 364 //
cannam@135 365 // Note that due to C++ rules about implicit copy constructors and assignment operators, any
cannam@135 366 // type that contains or inherits from a type that disallows const copies will also automatically
cannam@135 367 // disallow const copies. Hey, cool, that's exactly what we want.
cannam@135 368
cannam@135 369 DisallowConstCopy() = default;
cannam@135 370 DisallowConstCopy(DisallowConstCopy&) = default;
cannam@135 371 DisallowConstCopy(DisallowConstCopy&&) = default;
cannam@135 372 DisallowConstCopy& operator=(DisallowConstCopy&) = default;
cannam@135 373 DisallowConstCopy& operator=(DisallowConstCopy&&) = default;
cannam@135 374 };
cannam@135 375
cannam@135 376 template <typename T>
cannam@135 377 struct DisallowConstCopyIfNotConst: public DisallowConstCopy {
cannam@135 378 // Inherit from this when implementing a template that contains a pointer to T and which should
cannam@135 379 // enforce transitive constness. If T is a const type, this has no effect. Otherwise, it is
cannam@135 380 // an alias for DisallowConstCopy.
cannam@135 381 };
cannam@135 382
cannam@135 383 template <typename T>
cannam@135 384 struct DisallowConstCopyIfNotConst<const T> {};
cannam@135 385
cannam@135 386 template <typename T> struct IsConst_ { static constexpr bool value = false; };
cannam@135 387 template <typename T> struct IsConst_<const T> { static constexpr bool value = true; };
cannam@135 388 template <typename T> constexpr bool isConst() { return IsConst_<T>::value; }
cannam@135 389
cannam@135 390 template <typename T> struct EnableIfNotConst_ { typedef T Type; };
cannam@135 391 template <typename T> struct EnableIfNotConst_<const T>;
cannam@135 392 template <typename T> using EnableIfNotConst = typename EnableIfNotConst_<T>::Type;
cannam@135 393
cannam@135 394 template <typename T> struct EnableIfConst_;
cannam@135 395 template <typename T> struct EnableIfConst_<const T> { typedef T Type; };
cannam@135 396 template <typename T> using EnableIfConst = typename EnableIfConst_<T>::Type;
cannam@135 397
cannam@135 398 template <typename T> struct RemoveConstOrDisable_ { struct Type; };
cannam@135 399 template <typename T> struct RemoveConstOrDisable_<const T> { typedef T Type; };
cannam@135 400 template <typename T> using RemoveConstOrDisable = typename RemoveConstOrDisable_<T>::Type;
cannam@135 401
cannam@135 402 template <typename T> struct IsReference_ { static constexpr bool value = false; };
cannam@135 403 template <typename T> struct IsReference_<T&> { static constexpr bool value = true; };
cannam@135 404 template <typename T> constexpr bool isReference() { return IsReference_<T>::value; }
cannam@135 405
cannam@135 406 template <typename From, typename To>
cannam@135 407 struct PropagateConst_ { typedef To Type; };
cannam@135 408 template <typename From, typename To>
cannam@135 409 struct PropagateConst_<const From, To> { typedef const To Type; };
cannam@135 410 template <typename From, typename To>
cannam@135 411 using PropagateConst = typename PropagateConst_<From, To>::Type;
cannam@135 412
cannam@135 413 namespace _ { // private
cannam@135 414
cannam@135 415 template <typename T>
cannam@135 416 T refIfLvalue(T&&);
cannam@135 417
cannam@135 418 } // namespace _ (private)
cannam@135 419
cannam@135 420 #define KJ_DECLTYPE_REF(exp) decltype(::kj::_::refIfLvalue(exp))
cannam@135 421 // Like decltype(exp), but if exp is an lvalue, produces a reference type.
cannam@135 422 //
cannam@135 423 // int i;
cannam@135 424 // decltype(i) i1(i); // i1 has type int.
cannam@135 425 // KJ_DECLTYPE_REF(i + 1) i2(i + 1); // i2 has type int.
cannam@135 426 // KJ_DECLTYPE_REF(i) i3(i); // i3 has type int&.
cannam@135 427 // KJ_DECLTYPE_REF(kj::mv(i)) i4(kj::mv(i)); // i4 has type int.
cannam@135 428
cannam@135 429 template <typename T>
cannam@135 430 struct CanConvert_ {
cannam@135 431 static int sfinae(T);
cannam@135 432 static bool sfinae(...);
cannam@135 433 };
cannam@135 434
cannam@135 435 template <typename T, typename U>
cannam@135 436 constexpr bool canConvert() {
cannam@135 437 return sizeof(CanConvert_<U>::sfinae(instance<T>())) == sizeof(int);
cannam@135 438 }
cannam@135 439
cannam@135 440 #if __clang__
cannam@135 441 template <typename T>
cannam@135 442 constexpr bool canMemcpy() {
cannam@135 443 // Returns true if T can be copied using memcpy instead of using the copy constructor or
cannam@135 444 // assignment operator.
cannam@135 445
cannam@135 446 // Clang unhelpfully defines __has_trivial_{copy,assign}(T) to be true if the copy constructor /
cannam@135 447 // assign operator are deleted, on the basis that a strict reading of the definition of "trivial"
cannam@135 448 // according to the standard says that deleted functions are in fact trivial. Meanwhile Clang
cannam@135 449 // provides these admittedly-better intrinsics, but GCC does not.
cannam@135 450 return __is_trivially_constructible(T, const T&) && __is_trivially_assignable(T, const T&);
cannam@135 451 }
cannam@135 452 #else
cannam@135 453 template <typename T>
cannam@135 454 constexpr bool canMemcpy() {
cannam@135 455 // Returns true if T can be copied using memcpy instead of using the copy constructor or
cannam@135 456 // assignment operator.
cannam@135 457
cannam@135 458 // GCC defines these to mean what we want them to mean.
cannam@135 459 return __has_trivial_copy(T) && __has_trivial_assign(T);
cannam@135 460 }
cannam@135 461 #endif
cannam@135 462
cannam@135 463 // =======================================================================================
cannam@135 464 // Equivalents to std::move() and std::forward(), since these are very commonly needed and the
cannam@135 465 // std header <utility> pulls in lots of other stuff.
cannam@135 466 //
cannam@135 467 // We use abbreviated names mv and fwd because these helpers (especially mv) are so commonly used
cannam@135 468 // that the cost of typing more letters outweighs the cost of being slightly harder to understand
cannam@135 469 // when first encountered.
cannam@135 470
cannam@135 471 template<typename T> constexpr T&& mv(T& t) noexcept { return static_cast<T&&>(t); }
cannam@135 472 template<typename T> constexpr T&& fwd(NoInfer<T>& t) noexcept { return static_cast<T&&>(t); }
cannam@135 473
cannam@135 474 template<typename T> constexpr T cp(T& t) noexcept { return t; }
cannam@135 475 template<typename T> constexpr T cp(const T& t) noexcept { return t; }
cannam@135 476 // Useful to force a copy, particularly to pass into a function that expects T&&.
cannam@135 477
cannam@135 478 template <typename T, typename U, bool takeT> struct MinType_;
cannam@135 479 template <typename T, typename U> struct MinType_<T, U, true> { typedef T Type; };
cannam@135 480 template <typename T, typename U> struct MinType_<T, U, false> { typedef U Type; };
cannam@135 481
cannam@135 482 template <typename T, typename U>
cannam@135 483 using MinType = typename MinType_<T, U, sizeof(T) <= sizeof(U)>::Type;
cannam@135 484 // Resolves to the smaller of the two input types.
cannam@135 485
cannam@135 486 template <typename T, typename U>
cannam@135 487 inline constexpr auto min(T&& a, U&& b) -> MinType<Decay<T>, Decay<U>> {
cannam@135 488 return a < b ? MinType<Decay<T>, Decay<U>>(a) : MinType<Decay<T>, Decay<U>>(b);
cannam@135 489 }
cannam@135 490
cannam@135 491 template <typename T, typename U, bool takeT> struct MaxType_;
cannam@135 492 template <typename T, typename U> struct MaxType_<T, U, true> { typedef T Type; };
cannam@135 493 template <typename T, typename U> struct MaxType_<T, U, false> { typedef U Type; };
cannam@135 494
cannam@135 495 template <typename T, typename U>
cannam@135 496 using MaxType = typename MaxType_<T, U, sizeof(T) >= sizeof(U)>::Type;
cannam@135 497 // Resolves to the larger of the two input types.
cannam@135 498
cannam@135 499 template <typename T, typename U>
cannam@135 500 inline constexpr auto max(T&& a, U&& b) -> MaxType<Decay<T>, Decay<U>> {
cannam@135 501 return a > b ? MaxType<Decay<T>, Decay<U>>(a) : MaxType<Decay<T>, Decay<U>>(b);
cannam@135 502 }
cannam@135 503
cannam@135 504 template <typename T, size_t s>
cannam@135 505 inline constexpr size_t size(T (&arr)[s]) { return s; }
cannam@135 506 template <typename T>
cannam@135 507 inline constexpr size_t size(T&& arr) { return arr.size(); }
cannam@135 508 // Returns the size of the parameter, whether the parameter is a regular C array or a container
cannam@135 509 // with a `.size()` method.
cannam@135 510
cannam@135 511 class MaxValue_ {
cannam@135 512 private:
cannam@135 513 template <typename T>
cannam@135 514 inline constexpr T maxSigned() const {
cannam@135 515 return (1ull << (sizeof(T) * 8 - 1)) - 1;
cannam@135 516 }
cannam@135 517 template <typename T>
cannam@135 518 inline constexpr T maxUnsigned() const {
cannam@135 519 return ~static_cast<T>(0u);
cannam@135 520 }
cannam@135 521
cannam@135 522 public:
cannam@135 523 #define _kJ_HANDLE_TYPE(T) \
cannam@135 524 inline constexpr operator signed T() const { return MaxValue_::maxSigned < signed T>(); } \
cannam@135 525 inline constexpr operator unsigned T() const { return MaxValue_::maxUnsigned<unsigned T>(); }
cannam@135 526 _kJ_HANDLE_TYPE(char)
cannam@135 527 _kJ_HANDLE_TYPE(short)
cannam@135 528 _kJ_HANDLE_TYPE(int)
cannam@135 529 _kJ_HANDLE_TYPE(long)
cannam@135 530 _kJ_HANDLE_TYPE(long long)
cannam@135 531 #undef _kJ_HANDLE_TYPE
cannam@135 532
cannam@135 533 inline constexpr operator char() const {
cannam@135 534 // `char` is different from both `signed char` and `unsigned char`, and may be signed or
cannam@135 535 // unsigned on different platforms. Ugh.
cannam@135 536 return char(-1) < 0 ? MaxValue_::maxSigned<char>()
cannam@135 537 : MaxValue_::maxUnsigned<char>();
cannam@135 538 }
cannam@135 539 };
cannam@135 540
cannam@135 541 class MinValue_ {
cannam@135 542 private:
cannam@135 543 template <typename T>
cannam@135 544 inline constexpr T minSigned() const {
cannam@135 545 return 1ull << (sizeof(T) * 8 - 1);
cannam@135 546 }
cannam@135 547 template <typename T>
cannam@135 548 inline constexpr T minUnsigned() const {
cannam@135 549 return 0u;
cannam@135 550 }
cannam@135 551
cannam@135 552 public:
cannam@135 553 #define _kJ_HANDLE_TYPE(T) \
cannam@135 554 inline constexpr operator signed T() const { return MinValue_::minSigned < signed T>(); } \
cannam@135 555 inline constexpr operator unsigned T() const { return MinValue_::minUnsigned<unsigned T>(); }
cannam@135 556 _kJ_HANDLE_TYPE(char)
cannam@135 557 _kJ_HANDLE_TYPE(short)
cannam@135 558 _kJ_HANDLE_TYPE(int)
cannam@135 559 _kJ_HANDLE_TYPE(long)
cannam@135 560 _kJ_HANDLE_TYPE(long long)
cannam@135 561 #undef _kJ_HANDLE_TYPE
cannam@135 562
cannam@135 563 inline constexpr operator char() const {
cannam@135 564 // `char` is different from both `signed char` and `unsigned char`, and may be signed or
cannam@135 565 // unsigned on different platforms. Ugh.
cannam@135 566 return char(-1) < 0 ? MinValue_::minSigned<char>()
cannam@135 567 : MinValue_::minUnsigned<char>();
cannam@135 568 }
cannam@135 569 };
cannam@135 570
cannam@135 571 static KJ_CONSTEXPR(const) MaxValue_ maxValue = MaxValue_();
cannam@135 572 // A special constant which, when cast to an integer type, takes on the maximum possible value of
cannam@135 573 // that type. This is useful to use as e.g. a parameter to a function because it will be robust
cannam@135 574 // in the face of changes to the parameter's type.
cannam@135 575 //
cannam@135 576 // `char` is not supported, but `signed char` and `unsigned char` are.
cannam@135 577
cannam@135 578 static KJ_CONSTEXPR(const) MinValue_ minValue = MinValue_();
cannam@135 579 // A special constant which, when cast to an integer type, takes on the minimum possible value
cannam@135 580 // of that type. This is useful to use as e.g. a parameter to a function because it will be robust
cannam@135 581 // in the face of changes to the parameter's type.
cannam@135 582 //
cannam@135 583 // `char` is not supported, but `signed char` and `unsigned char` are.
cannam@135 584
cannam@135 585 #if __GNUC__
cannam@135 586 inline constexpr float inf() { return __builtin_huge_valf(); }
cannam@135 587 inline constexpr float nan() { return __builtin_nanf(""); }
cannam@135 588
cannam@135 589 #elif _MSC_VER
cannam@135 590
cannam@135 591 // Do what MSVC math.h does
cannam@135 592 #pragma warning(push)
cannam@135 593 #pragma warning(disable: 4756) // "overflow in constant arithmetic"
cannam@135 594 inline constexpr float inf() { return (float)(1e300 * 1e300); }
cannam@135 595 #pragma warning(pop)
cannam@135 596
cannam@135 597 float nan();
cannam@135 598 // Unfortunatley, inf() * 0.0f produces a NaN with the sign bit set, whereas our preferred
cannam@135 599 // canonical NaN should not have the sign bit set. std::numeric_limits<float>::quiet_NaN()
cannam@135 600 // returns the correct NaN, but we don't want to #include that here. So, we give up and make
cannam@135 601 // this out-of-line on MSVC.
cannam@135 602 //
cannam@135 603 // TODO(msvc): Can we do better?
cannam@135 604
cannam@135 605 #else
cannam@135 606 #error "Not sure how to support your compiler."
cannam@135 607 #endif
cannam@135 608
cannam@135 609 inline constexpr bool isNaN(float f) { return f != f; }
cannam@135 610 inline constexpr bool isNaN(double f) { return f != f; }
cannam@135 611
cannam@135 612 inline int popCount(unsigned int x) {
cannam@135 613 #if defined(_MSC_VER)
cannam@135 614 return __popcnt(x);
cannam@135 615 // Note: __popcnt returns unsigned int, but the value is clearly guaranteed to fit into an int
cannam@135 616 #else
cannam@135 617 return __builtin_popcount(x);
cannam@135 618 #endif
cannam@135 619 }
cannam@135 620
cannam@135 621 // =======================================================================================
cannam@135 622 // Useful fake containers
cannam@135 623
cannam@135 624 template <typename T>
cannam@135 625 class Range {
cannam@135 626 public:
cannam@135 627 inline constexpr Range(const T& begin, const T& end): begin_(begin), end_(end) {}
cannam@135 628
cannam@135 629 class Iterator {
cannam@135 630 public:
cannam@135 631 Iterator() = default;
cannam@135 632 inline Iterator(const T& value): value(value) {}
cannam@135 633
cannam@135 634 inline const T& operator* () const { return value; }
cannam@135 635 inline const T& operator[](size_t index) const { return value + index; }
cannam@135 636 inline Iterator& operator++() { ++value; return *this; }
cannam@135 637 inline Iterator operator++(int) { return Iterator(value++); }
cannam@135 638 inline Iterator& operator--() { --value; return *this; }
cannam@135 639 inline Iterator operator--(int) { return Iterator(value--); }
cannam@135 640 inline Iterator& operator+=(ptrdiff_t amount) { value += amount; return *this; }
cannam@135 641 inline Iterator& operator-=(ptrdiff_t amount) { value -= amount; return *this; }
cannam@135 642 inline Iterator operator+ (ptrdiff_t amount) const { return Iterator(value + amount); }
cannam@135 643 inline Iterator operator- (ptrdiff_t amount) const { return Iterator(value - amount); }
cannam@135 644 inline ptrdiff_t operator- (const Iterator& other) const { return value - other.value; }
cannam@135 645
cannam@135 646 inline bool operator==(const Iterator& other) const { return value == other.value; }
cannam@135 647 inline bool operator!=(const Iterator& other) const { return value != other.value; }
cannam@135 648 inline bool operator<=(const Iterator& other) const { return value <= other.value; }
cannam@135 649 inline bool operator>=(const Iterator& other) const { return value >= other.value; }
cannam@135 650 inline bool operator< (const Iterator& other) const { return value < other.value; }
cannam@135 651 inline bool operator> (const Iterator& other) const { return value > other.value; }
cannam@135 652
cannam@135 653 private:
cannam@135 654 T value;
cannam@135 655 };
cannam@135 656
cannam@135 657 inline Iterator begin() const { return Iterator(begin_); }
cannam@135 658 inline Iterator end() const { return Iterator(end_); }
cannam@135 659
cannam@135 660 inline auto size() const -> decltype(instance<T>() - instance<T>()) { return end_ - begin_; }
cannam@135 661
cannam@135 662 private:
cannam@135 663 T begin_;
cannam@135 664 T end_;
cannam@135 665 };
cannam@135 666
cannam@135 667 template <typename T>
cannam@135 668 inline constexpr Range<Decay<T>> range(T begin, T end) { return Range<Decay<T>>(begin, end); }
cannam@135 669 // Returns a fake iterable container containing all values of T from `begin` (inclusive) to `end`
cannam@135 670 // (exclusive). Example:
cannam@135 671 //
cannam@135 672 // // Prints 1, 2, 3, 4, 5, 6, 7, 8, 9.
cannam@135 673 // for (int i: kj::range(1, 10)) { print(i); }
cannam@135 674
cannam@135 675 template <typename T>
cannam@135 676 inline constexpr Range<size_t> indices(T&& container) {
cannam@135 677 // Shortcut for iterating over the indices of a container:
cannam@135 678 //
cannam@135 679 // for (size_t i: kj::indices(myArray)) { handle(myArray[i]); }
cannam@135 680
cannam@135 681 return range<size_t>(0, kj::size(container));
cannam@135 682 }
cannam@135 683
cannam@135 684 template <typename T>
cannam@135 685 class Repeat {
cannam@135 686 public:
cannam@135 687 inline constexpr Repeat(const T& value, size_t count): value(value), count(count) {}
cannam@135 688
cannam@135 689 class Iterator {
cannam@135 690 public:
cannam@135 691 Iterator() = default;
cannam@135 692 inline Iterator(const T& value, size_t index): value(value), index(index) {}
cannam@135 693
cannam@135 694 inline const T& operator* () const { return value; }
cannam@135 695 inline const T& operator[](ptrdiff_t index) const { return value; }
cannam@135 696 inline Iterator& operator++() { ++index; return *this; }
cannam@135 697 inline Iterator operator++(int) { return Iterator(value, index++); }
cannam@135 698 inline Iterator& operator--() { --index; return *this; }
cannam@135 699 inline Iterator operator--(int) { return Iterator(value, index--); }
cannam@135 700 inline Iterator& operator+=(ptrdiff_t amount) { index += amount; return *this; }
cannam@135 701 inline Iterator& operator-=(ptrdiff_t amount) { index -= amount; return *this; }
cannam@135 702 inline Iterator operator+ (ptrdiff_t amount) const { return Iterator(value, index + amount); }
cannam@135 703 inline Iterator operator- (ptrdiff_t amount) const { return Iterator(value, index - amount); }
cannam@135 704 inline ptrdiff_t operator- (const Iterator& other) const { return index - other.index; }
cannam@135 705
cannam@135 706 inline bool operator==(const Iterator& other) const { return index == other.index; }
cannam@135 707 inline bool operator!=(const Iterator& other) const { return index != other.index; }
cannam@135 708 inline bool operator<=(const Iterator& other) const { return index <= other.index; }
cannam@135 709 inline bool operator>=(const Iterator& other) const { return index >= other.index; }
cannam@135 710 inline bool operator< (const Iterator& other) const { return index < other.index; }
cannam@135 711 inline bool operator> (const Iterator& other) const { return index > other.index; }
cannam@135 712
cannam@135 713 private:
cannam@135 714 T value;
cannam@135 715 size_t index;
cannam@135 716 };
cannam@135 717
cannam@135 718 inline Iterator begin() const { return Iterator(value, 0); }
cannam@135 719 inline Iterator end() const { return Iterator(value, count); }
cannam@135 720
cannam@135 721 inline size_t size() const { return count; }
cannam@135 722
cannam@135 723 private:
cannam@135 724 T value;
cannam@135 725 size_t count;
cannam@135 726 };
cannam@135 727
cannam@135 728 template <typename T>
cannam@135 729 inline constexpr Repeat<Decay<T>> repeat(T&& value, size_t count) {
cannam@135 730 // Returns a fake iterable which contains `count` repeats of `value`. Useful for e.g. creating
cannam@135 731 // a bunch of spaces: `kj::repeat(' ', indent * 2)`
cannam@135 732
cannam@135 733 return Repeat<Decay<T>>(value, count);
cannam@135 734 }
cannam@135 735
cannam@135 736 // =======================================================================================
cannam@135 737 // Manually invoking constructors and destructors
cannam@135 738 //
cannam@135 739 // ctor(x, ...) and dtor(x) invoke x's constructor or destructor, respectively.
cannam@135 740
cannam@135 741 // We want placement new, but we don't want to #include <new>. operator new cannot be defined in
cannam@135 742 // a namespace, and defining it globally conflicts with the definition in <new>. So we have to
cannam@135 743 // define a dummy type and an operator new that uses it.
cannam@135 744
cannam@135 745 namespace _ { // private
cannam@135 746 struct PlacementNew {};
cannam@135 747 } // namespace _ (private)
cannam@135 748 } // namespace kj
cannam@135 749
cannam@135 750 inline void* operator new(size_t, kj::_::PlacementNew, void* __p) noexcept {
cannam@135 751 return __p;
cannam@135 752 }
cannam@135 753
cannam@135 754 inline void operator delete(void*, kj::_::PlacementNew, void* __p) noexcept {}
cannam@135 755
cannam@135 756 namespace kj {
cannam@135 757
cannam@135 758 template <typename T, typename... Params>
cannam@135 759 inline void ctor(T& location, Params&&... params) {
cannam@135 760 new (_::PlacementNew(), &location) T(kj::fwd<Params>(params)...);
cannam@135 761 }
cannam@135 762
cannam@135 763 template <typename T>
cannam@135 764 inline void dtor(T& location) {
cannam@135 765 location.~T();
cannam@135 766 }
cannam@135 767
cannam@135 768 // =======================================================================================
cannam@135 769 // Maybe
cannam@135 770 //
cannam@135 771 // Use in cases where you want to indicate that a value may be null. Using Maybe<T&> instead of T*
cannam@135 772 // forces the caller to handle the null case in order to satisfy the compiler, thus reliably
cannam@135 773 // preventing null pointer dereferences at runtime.
cannam@135 774 //
cannam@135 775 // Maybe<T> can be implicitly constructed from T and from nullptr. Additionally, it can be
cannam@135 776 // implicitly constructed from T*, in which case the pointer is checked for nullness at runtime.
cannam@135 777 // To read the value of a Maybe<T>, do:
cannam@135 778 //
cannam@135 779 // KJ_IF_MAYBE(value, someFuncReturningMaybe()) {
cannam@135 780 // doSomething(*value);
cannam@135 781 // } else {
cannam@135 782 // maybeWasNull();
cannam@135 783 // }
cannam@135 784 //
cannam@135 785 // KJ_IF_MAYBE's first parameter is a variable name which will be defined within the following
cannam@135 786 // block. The variable will behave like a (guaranteed non-null) pointer to the Maybe's value,
cannam@135 787 // though it may or may not actually be a pointer.
cannam@135 788 //
cannam@135 789 // Note that Maybe<T&> actually just wraps a pointer, whereas Maybe<T> wraps a T and a boolean
cannam@135 790 // indicating nullness.
cannam@135 791
cannam@135 792 template <typename T>
cannam@135 793 class Maybe;
cannam@135 794
cannam@135 795 namespace _ { // private
cannam@135 796
cannam@135 797 #if _MSC_VER
cannam@135 798 // TODO(msvc): MSVC barfs on noexcept(instance<T&>().~T()) where T = kj::Exception and
cannam@135 799 // kj::_::Void. It and every other factorization I've tried produces:
cannam@135 800 // error C2325: 'kj::Blah' unexpected type to the right of '.~': expected 'void'
cannam@135 801 #define MSVC_NOEXCEPT_DTOR_WORKAROUND(T) __is_nothrow_destructible(T)
cannam@135 802 #else
cannam@135 803 #define MSVC_NOEXCEPT_DTOR_WORKAROUND(T) noexcept(instance<T&>().~T())
cannam@135 804 #endif
cannam@135 805
cannam@135 806 template <typename T>
cannam@135 807 class NullableValue {
cannam@135 808 // Class whose interface behaves much like T*, but actually contains an instance of T and a
cannam@135 809 // boolean flag indicating nullness.
cannam@135 810
cannam@135 811 public:
cannam@135 812 inline NullableValue(NullableValue&& other) noexcept(noexcept(T(instance<T&&>())))
cannam@135 813 : isSet(other.isSet) {
cannam@135 814 if (isSet) {
cannam@135 815 ctor(value, kj::mv(other.value));
cannam@135 816 }
cannam@135 817 }
cannam@135 818 inline NullableValue(const NullableValue& other)
cannam@135 819 : isSet(other.isSet) {
cannam@135 820 if (isSet) {
cannam@135 821 ctor(value, other.value);
cannam@135 822 }
cannam@135 823 }
cannam@135 824 inline NullableValue(NullableValue& other)
cannam@135 825 : isSet(other.isSet) {
cannam@135 826 if (isSet) {
cannam@135 827 ctor(value, other.value);
cannam@135 828 }
cannam@135 829 }
cannam@135 830 inline ~NullableValue() noexcept(MSVC_NOEXCEPT_DTOR_WORKAROUND(T)) {
cannam@135 831 if (isSet) {
cannam@135 832 dtor(value);
cannam@135 833 }
cannam@135 834 }
cannam@135 835
cannam@135 836 inline T& operator*() & { return value; }
cannam@135 837 inline const T& operator*() const & { return value; }
cannam@135 838 inline T&& operator*() && { return kj::mv(value); }
cannam@135 839 inline const T&& operator*() const && { return kj::mv(value); }
cannam@135 840 inline T* operator->() { return &value; }
cannam@135 841 inline const T* operator->() const { return &value; }
cannam@135 842 inline operator T*() { return isSet ? &value : nullptr; }
cannam@135 843 inline operator const T*() const { return isSet ? &value : nullptr; }
cannam@135 844
cannam@135 845 template <typename... Params>
cannam@135 846 inline T& emplace(Params&&... params) {
cannam@135 847 if (isSet) {
cannam@135 848 isSet = false;
cannam@135 849 dtor(value);
cannam@135 850 }
cannam@135 851 ctor(value, kj::fwd<Params>(params)...);
cannam@135 852 isSet = true;
cannam@135 853 return value;
cannam@135 854 }
cannam@135 855
cannam@135 856 private: // internal interface used by friends only
cannam@135 857 inline NullableValue() noexcept: isSet(false) {}
cannam@135 858 inline NullableValue(T&& t) noexcept(noexcept(T(instance<T&&>())))
cannam@135 859 : isSet(true) {
cannam@135 860 ctor(value, kj::mv(t));
cannam@135 861 }
cannam@135 862 inline NullableValue(T& t)
cannam@135 863 : isSet(true) {
cannam@135 864 ctor(value, t);
cannam@135 865 }
cannam@135 866 inline NullableValue(const T& t)
cannam@135 867 : isSet(true) {
cannam@135 868 ctor(value, t);
cannam@135 869 }
cannam@135 870 inline NullableValue(const T* t)
cannam@135 871 : isSet(t != nullptr) {
cannam@135 872 if (isSet) ctor(value, *t);
cannam@135 873 }
cannam@135 874 template <typename U>
cannam@135 875 inline NullableValue(NullableValue<U>&& other) noexcept(noexcept(T(instance<U&&>())))
cannam@135 876 : isSet(other.isSet) {
cannam@135 877 if (isSet) {
cannam@135 878 ctor(value, kj::mv(other.value));
cannam@135 879 }
cannam@135 880 }
cannam@135 881 template <typename U>
cannam@135 882 inline NullableValue(const NullableValue<U>& other)
cannam@135 883 : isSet(other.isSet) {
cannam@135 884 if (isSet) {
cannam@135 885 ctor(value, other.value);
cannam@135 886 }
cannam@135 887 }
cannam@135 888 template <typename U>
cannam@135 889 inline NullableValue(const NullableValue<U&>& other)
cannam@135 890 : isSet(other.isSet) {
cannam@135 891 if (isSet) {
cannam@135 892 ctor(value, *other.ptr);
cannam@135 893 }
cannam@135 894 }
cannam@135 895 inline NullableValue(decltype(nullptr)): isSet(false) {}
cannam@135 896
cannam@135 897 inline NullableValue& operator=(NullableValue&& other) {
cannam@135 898 if (&other != this) {
cannam@135 899 // Careful about throwing destructors/constructors here.
cannam@135 900 if (isSet) {
cannam@135 901 isSet = false;
cannam@135 902 dtor(value);
cannam@135 903 }
cannam@135 904 if (other.isSet) {
cannam@135 905 ctor(value, kj::mv(other.value));
cannam@135 906 isSet = true;
cannam@135 907 }
cannam@135 908 }
cannam@135 909 return *this;
cannam@135 910 }
cannam@135 911
cannam@135 912 inline NullableValue& operator=(NullableValue& other) {
cannam@135 913 if (&other != this) {
cannam@135 914 // Careful about throwing destructors/constructors here.
cannam@135 915 if (isSet) {
cannam@135 916 isSet = false;
cannam@135 917 dtor(value);
cannam@135 918 }
cannam@135 919 if (other.isSet) {
cannam@135 920 ctor(value, other.value);
cannam@135 921 isSet = true;
cannam@135 922 }
cannam@135 923 }
cannam@135 924 return *this;
cannam@135 925 }
cannam@135 926
cannam@135 927 inline NullableValue& operator=(const NullableValue& other) {
cannam@135 928 if (&other != this) {
cannam@135 929 // Careful about throwing destructors/constructors here.
cannam@135 930 if (isSet) {
cannam@135 931 isSet = false;
cannam@135 932 dtor(value);
cannam@135 933 }
cannam@135 934 if (other.isSet) {
cannam@135 935 ctor(value, other.value);
cannam@135 936 isSet = true;
cannam@135 937 }
cannam@135 938 }
cannam@135 939 return *this;
cannam@135 940 }
cannam@135 941
cannam@135 942 inline bool operator==(decltype(nullptr)) const { return !isSet; }
cannam@135 943 inline bool operator!=(decltype(nullptr)) const { return isSet; }
cannam@135 944
cannam@135 945 private:
cannam@135 946 bool isSet;
cannam@135 947
cannam@135 948 #if _MSC_VER
cannam@135 949 #pragma warning(push)
cannam@135 950 #pragma warning(disable: 4624)
cannam@135 951 // Warns that the anonymous union has a deleted destructor when T is non-trivial. This warning
cannam@135 952 // seems broken.
cannam@135 953 #endif
cannam@135 954
cannam@135 955 union {
cannam@135 956 T value;
cannam@135 957 };
cannam@135 958
cannam@135 959 #if _MSC_VER
cannam@135 960 #pragma warning(pop)
cannam@135 961 #endif
cannam@135 962
cannam@135 963 friend class kj::Maybe<T>;
cannam@135 964 template <typename U>
cannam@135 965 friend NullableValue<U>&& readMaybe(Maybe<U>&& maybe);
cannam@135 966 };
cannam@135 967
cannam@135 968 template <typename T>
cannam@135 969 inline NullableValue<T>&& readMaybe(Maybe<T>&& maybe) { return kj::mv(maybe.ptr); }
cannam@135 970 template <typename T>
cannam@135 971 inline T* readMaybe(Maybe<T>& maybe) { return maybe.ptr; }
cannam@135 972 template <typename T>
cannam@135 973 inline const T* readMaybe(const Maybe<T>& maybe) { return maybe.ptr; }
cannam@135 974 template <typename T>
cannam@135 975 inline T* readMaybe(Maybe<T&>&& maybe) { return maybe.ptr; }
cannam@135 976 template <typename T>
cannam@135 977 inline T* readMaybe(const Maybe<T&>& maybe) { return maybe.ptr; }
cannam@135 978
cannam@135 979 template <typename T>
cannam@135 980 inline T* readMaybe(T* ptr) { return ptr; }
cannam@135 981 // Allow KJ_IF_MAYBE to work on regular pointers.
cannam@135 982
cannam@135 983 } // namespace _ (private)
cannam@135 984
cannam@135 985 #define KJ_IF_MAYBE(name, exp) if (auto name = ::kj::_::readMaybe(exp))
cannam@135 986
cannam@135 987 template <typename T>
cannam@135 988 class Maybe {
cannam@135 989 // A T, or nullptr.
cannam@135 990
cannam@135 991 // IF YOU CHANGE THIS CLASS: Note that there is a specialization of it in memory.h.
cannam@135 992
cannam@135 993 public:
cannam@135 994 Maybe(): ptr(nullptr) {}
cannam@135 995 Maybe(T&& t) noexcept(noexcept(T(instance<T&&>()))): ptr(kj::mv(t)) {}
cannam@135 996 Maybe(T& t): ptr(t) {}
cannam@135 997 Maybe(const T& t): ptr(t) {}
cannam@135 998 Maybe(const T* t) noexcept: ptr(t) {}
cannam@135 999 Maybe(Maybe&& other) noexcept(noexcept(T(instance<T&&>()))): ptr(kj::mv(other.ptr)) {}
cannam@135 1000 Maybe(const Maybe& other): ptr(other.ptr) {}
cannam@135 1001 Maybe(Maybe& other): ptr(other.ptr) {}
cannam@135 1002
cannam@135 1003 template <typename U>
cannam@135 1004 Maybe(Maybe<U>&& other) noexcept(noexcept(T(instance<U&&>()))) {
cannam@135 1005 KJ_IF_MAYBE(val, kj::mv(other)) {
cannam@135 1006 ptr = *val;
cannam@135 1007 }
cannam@135 1008 }
cannam@135 1009 template <typename U>
cannam@135 1010 Maybe(const Maybe<U>& other) {
cannam@135 1011 KJ_IF_MAYBE(val, other) {
cannam@135 1012 ptr = *val;
cannam@135 1013 }
cannam@135 1014 }
cannam@135 1015
cannam@135 1016 Maybe(decltype(nullptr)) noexcept: ptr(nullptr) {}
cannam@135 1017
cannam@135 1018 template <typename... Params>
cannam@135 1019 inline T& emplace(Params&&... params) {
cannam@135 1020 // Replace this Maybe's content with a new value constructed by passing the given parametrs to
cannam@135 1021 // T's constructor. This can be used to initialize a Maybe without copying or even moving a T.
cannam@135 1022 // Returns a reference to the newly-constructed value.
cannam@135 1023
cannam@135 1024 return ptr.emplace(kj::fwd<Params>(params)...);
cannam@135 1025 }
cannam@135 1026
cannam@135 1027 inline Maybe& operator=(Maybe&& other) { ptr = kj::mv(other.ptr); return *this; }
cannam@135 1028 inline Maybe& operator=(Maybe& other) { ptr = other.ptr; return *this; }
cannam@135 1029 inline Maybe& operator=(const Maybe& other) { ptr = other.ptr; return *this; }
cannam@135 1030
cannam@135 1031 inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; }
cannam@135 1032 inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; }
cannam@135 1033
cannam@135 1034 T& orDefault(T& defaultValue) {
cannam@135 1035 if (ptr == nullptr) {
cannam@135 1036 return defaultValue;
cannam@135 1037 } else {
cannam@135 1038 return *ptr;
cannam@135 1039 }
cannam@135 1040 }
cannam@135 1041 const T& orDefault(const T& defaultValue) const {
cannam@135 1042 if (ptr == nullptr) {
cannam@135 1043 return defaultValue;
cannam@135 1044 } else {
cannam@135 1045 return *ptr;
cannam@135 1046 }
cannam@135 1047 }
cannam@135 1048
cannam@135 1049 template <typename Func>
cannam@135 1050 auto map(Func&& f) & -> Maybe<decltype(f(instance<T&>()))> {
cannam@135 1051 if (ptr == nullptr) {
cannam@135 1052 return nullptr;
cannam@135 1053 } else {
cannam@135 1054 return f(*ptr);
cannam@135 1055 }
cannam@135 1056 }
cannam@135 1057
cannam@135 1058 template <typename Func>
cannam@135 1059 auto map(Func&& f) const & -> Maybe<decltype(f(instance<const T&>()))> {
cannam@135 1060 if (ptr == nullptr) {
cannam@135 1061 return nullptr;
cannam@135 1062 } else {
cannam@135 1063 return f(*ptr);
cannam@135 1064 }
cannam@135 1065 }
cannam@135 1066
cannam@135 1067 template <typename Func>
cannam@135 1068 auto map(Func&& f) && -> Maybe<decltype(f(instance<T&&>()))> {
cannam@135 1069 if (ptr == nullptr) {
cannam@135 1070 return nullptr;
cannam@135 1071 } else {
cannam@135 1072 return f(kj::mv(*ptr));
cannam@135 1073 }
cannam@135 1074 }
cannam@135 1075
cannam@135 1076 template <typename Func>
cannam@135 1077 auto map(Func&& f) const && -> Maybe<decltype(f(instance<const T&&>()))> {
cannam@135 1078 if (ptr == nullptr) {
cannam@135 1079 return nullptr;
cannam@135 1080 } else {
cannam@135 1081 return f(kj::mv(*ptr));
cannam@135 1082 }
cannam@135 1083 }
cannam@135 1084
cannam@135 1085 private:
cannam@135 1086 _::NullableValue<T> ptr;
cannam@135 1087
cannam@135 1088 template <typename U>
cannam@135 1089 friend class Maybe;
cannam@135 1090 template <typename U>
cannam@135 1091 friend _::NullableValue<U>&& _::readMaybe(Maybe<U>&& maybe);
cannam@135 1092 template <typename U>
cannam@135 1093 friend U* _::readMaybe(Maybe<U>& maybe);
cannam@135 1094 template <typename U>
cannam@135 1095 friend const U* _::readMaybe(const Maybe<U>& maybe);
cannam@135 1096 };
cannam@135 1097
cannam@135 1098 template <typename T>
cannam@135 1099 class Maybe<T&>: public DisallowConstCopyIfNotConst<T> {
cannam@135 1100 public:
cannam@135 1101 Maybe() noexcept: ptr(nullptr) {}
cannam@135 1102 Maybe(T& t) noexcept: ptr(&t) {}
cannam@135 1103 Maybe(T* t) noexcept: ptr(t) {}
cannam@135 1104
cannam@135 1105 template <typename U>
cannam@135 1106 inline Maybe(Maybe<U&>& other) noexcept: ptr(other.ptr) {}
cannam@135 1107 template <typename U>
cannam@135 1108 inline Maybe(const Maybe<const U&>& other) noexcept: ptr(other.ptr) {}
cannam@135 1109 inline Maybe(decltype(nullptr)) noexcept: ptr(nullptr) {}
cannam@135 1110
cannam@135 1111 inline Maybe& operator=(T& other) noexcept { ptr = &other; return *this; }
cannam@135 1112 inline Maybe& operator=(T* other) noexcept { ptr = other; return *this; }
cannam@135 1113 template <typename U>
cannam@135 1114 inline Maybe& operator=(Maybe<U&>& other) noexcept { ptr = other.ptr; return *this; }
cannam@135 1115 template <typename U>
cannam@135 1116 inline Maybe& operator=(const Maybe<const U&>& other) noexcept { ptr = other.ptr; return *this; }
cannam@135 1117
cannam@135 1118 inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; }
cannam@135 1119 inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; }
cannam@135 1120
cannam@135 1121 T& orDefault(T& defaultValue) {
cannam@135 1122 if (ptr == nullptr) {
cannam@135 1123 return defaultValue;
cannam@135 1124 } else {
cannam@135 1125 return *ptr;
cannam@135 1126 }
cannam@135 1127 }
cannam@135 1128 const T& orDefault(const T& defaultValue) const {
cannam@135 1129 if (ptr == nullptr) {
cannam@135 1130 return defaultValue;
cannam@135 1131 } else {
cannam@135 1132 return *ptr;
cannam@135 1133 }
cannam@135 1134 }
cannam@135 1135
cannam@135 1136 template <typename Func>
cannam@135 1137 auto map(Func&& f) -> Maybe<decltype(f(instance<T&>()))> {
cannam@135 1138 if (ptr == nullptr) {
cannam@135 1139 return nullptr;
cannam@135 1140 } else {
cannam@135 1141 return f(*ptr);
cannam@135 1142 }
cannam@135 1143 }
cannam@135 1144
cannam@135 1145 private:
cannam@135 1146 T* ptr;
cannam@135 1147
cannam@135 1148 template <typename U>
cannam@135 1149 friend class Maybe;
cannam@135 1150 template <typename U>
cannam@135 1151 friend U* _::readMaybe(Maybe<U&>&& maybe);
cannam@135 1152 template <typename U>
cannam@135 1153 friend U* _::readMaybe(const Maybe<U&>& maybe);
cannam@135 1154 };
cannam@135 1155
cannam@135 1156 // =======================================================================================
cannam@135 1157 // ArrayPtr
cannam@135 1158 //
cannam@135 1159 // So common that we put it in common.h rather than array.h.
cannam@135 1160
cannam@135 1161 template <typename T>
cannam@135 1162 class ArrayPtr: public DisallowConstCopyIfNotConst<T> {
cannam@135 1163 // A pointer to an array. Includes a size. Like any pointer, it doesn't own the target data,
cannam@135 1164 // and passing by value only copies the pointer, not the target.
cannam@135 1165
cannam@135 1166 public:
cannam@135 1167 inline constexpr ArrayPtr(): ptr(nullptr), size_(0) {}
cannam@135 1168 inline constexpr ArrayPtr(decltype(nullptr)): ptr(nullptr), size_(0) {}
cannam@135 1169 inline constexpr ArrayPtr(T* ptr, size_t size): ptr(ptr), size_(size) {}
cannam@135 1170 inline constexpr ArrayPtr(T* begin, T* end): ptr(begin), size_(end - begin) {}
cannam@135 1171 inline KJ_CONSTEXPR() ArrayPtr(::std::initializer_list<RemoveConstOrDisable<T>> init)
cannam@135 1172 : ptr(init.begin()), size_(init.size()) {}
cannam@135 1173
cannam@135 1174 template <size_t size>
cannam@135 1175 inline constexpr ArrayPtr(T (&native)[size]): ptr(native), size_(size) {}
cannam@135 1176 // Construct an ArrayPtr from a native C-style array.
cannam@135 1177
cannam@135 1178 inline operator ArrayPtr<const T>() const {
cannam@135 1179 return ArrayPtr<const T>(ptr, size_);
cannam@135 1180 }
cannam@135 1181 inline ArrayPtr<const T> asConst() const {
cannam@135 1182 return ArrayPtr<const T>(ptr, size_);
cannam@135 1183 }
cannam@135 1184
cannam@135 1185 inline size_t size() const { return size_; }
cannam@135 1186 inline const T& operator[](size_t index) const {
cannam@135 1187 KJ_IREQUIRE(index < size_, "Out-of-bounds ArrayPtr access.");
cannam@135 1188 return ptr[index];
cannam@135 1189 }
cannam@135 1190 inline T& operator[](size_t index) {
cannam@135 1191 KJ_IREQUIRE(index < size_, "Out-of-bounds ArrayPtr access.");
cannam@135 1192 return ptr[index];
cannam@135 1193 }
cannam@135 1194
cannam@135 1195 inline T* begin() { return ptr; }
cannam@135 1196 inline T* end() { return ptr + size_; }
cannam@135 1197 inline T& front() { return *ptr; }
cannam@135 1198 inline T& back() { return *(ptr + size_ - 1); }
cannam@135 1199 inline const T* begin() const { return ptr; }
cannam@135 1200 inline const T* end() const { return ptr + size_; }
cannam@135 1201 inline const T& front() const { return *ptr; }
cannam@135 1202 inline const T& back() const { return *(ptr + size_ - 1); }
cannam@135 1203
cannam@135 1204 inline ArrayPtr<const T> slice(size_t start, size_t end) const {
cannam@135 1205 KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds ArrayPtr::slice().");
cannam@135 1206 return ArrayPtr<const T>(ptr + start, end - start);
cannam@135 1207 }
cannam@135 1208 inline ArrayPtr slice(size_t start, size_t end) {
cannam@135 1209 KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds ArrayPtr::slice().");
cannam@135 1210 return ArrayPtr(ptr + start, end - start);
cannam@135 1211 }
cannam@135 1212
cannam@135 1213 inline ArrayPtr<PropagateConst<T, byte>> asBytes() const {
cannam@135 1214 // Reinterpret the array as a byte array. This is explicitly legal under C++ aliasing
cannam@135 1215 // rules.
cannam@135 1216 return { reinterpret_cast<PropagateConst<T, byte>*>(ptr), size_ * sizeof(T) };
cannam@135 1217 }
cannam@135 1218 inline ArrayPtr<PropagateConst<T, char>> asChars() const {
cannam@135 1219 // Reinterpret the array as a char array. This is explicitly legal under C++ aliasing
cannam@135 1220 // rules.
cannam@135 1221 return { reinterpret_cast<PropagateConst<T, char>*>(ptr), size_ * sizeof(T) };
cannam@135 1222 }
cannam@135 1223
cannam@135 1224 inline bool operator==(decltype(nullptr)) const { return size_ == 0; }
cannam@135 1225 inline bool operator!=(decltype(nullptr)) const { return size_ != 0; }
cannam@135 1226
cannam@135 1227 inline bool operator==(const ArrayPtr& other) const {
cannam@135 1228 if (size_ != other.size_) return false;
cannam@135 1229 for (size_t i = 0; i < size_; i++) {
cannam@135 1230 if (ptr[i] != other[i]) return false;
cannam@135 1231 }
cannam@135 1232 return true;
cannam@135 1233 }
cannam@135 1234 inline bool operator!=(const ArrayPtr& other) const { return !(*this == other); }
cannam@135 1235
cannam@135 1236 private:
cannam@135 1237 T* ptr;
cannam@135 1238 size_t size_;
cannam@135 1239 };
cannam@135 1240
cannam@135 1241 template <typename T>
cannam@135 1242 inline constexpr ArrayPtr<T> arrayPtr(T* ptr, size_t size) {
cannam@135 1243 // Use this function to construct ArrayPtrs without writing out the type name.
cannam@135 1244 return ArrayPtr<T>(ptr, size);
cannam@135 1245 }
cannam@135 1246
cannam@135 1247 template <typename T>
cannam@135 1248 inline constexpr ArrayPtr<T> arrayPtr(T* begin, T* end) {
cannam@135 1249 // Use this function to construct ArrayPtrs without writing out the type name.
cannam@135 1250 return ArrayPtr<T>(begin, end);
cannam@135 1251 }
cannam@135 1252
cannam@135 1253 // =======================================================================================
cannam@135 1254 // Casts
cannam@135 1255
cannam@135 1256 template <typename To, typename From>
cannam@135 1257 To implicitCast(From&& from) {
cannam@135 1258 // `implicitCast<T>(value)` casts `value` to type `T` only if the conversion is implicit. Useful
cannam@135 1259 // for e.g. resolving ambiguous overloads without sacrificing type-safety.
cannam@135 1260 return kj::fwd<From>(from);
cannam@135 1261 }
cannam@135 1262
cannam@135 1263 template <typename To, typename From>
cannam@135 1264 Maybe<To&> dynamicDowncastIfAvailable(From& from) {
cannam@135 1265 // If RTTI is disabled, always returns nullptr. Otherwise, works like dynamic_cast. Useful
cannam@135 1266 // in situations where dynamic_cast could allow an optimization, but isn't strictly necessary
cannam@135 1267 // for correctness. It is highly recommended that you try to arrange all your dynamic_casts
cannam@135 1268 // this way, as a dynamic_cast that is necessary for correctness implies a flaw in the interface
cannam@135 1269 // design.
cannam@135 1270
cannam@135 1271 // Force a compile error if To is not a subtype of From. Cross-casting is rare; if it is needed
cannam@135 1272 // we should have a separate cast function like dynamicCrosscastIfAvailable().
cannam@135 1273 if (false) {
cannam@135 1274 kj::implicitCast<From*>(kj::implicitCast<To*>(nullptr));
cannam@135 1275 }
cannam@135 1276
cannam@135 1277 #if KJ_NO_RTTI
cannam@135 1278 return nullptr;
cannam@135 1279 #else
cannam@135 1280 return dynamic_cast<To*>(&from);
cannam@135 1281 #endif
cannam@135 1282 }
cannam@135 1283
cannam@135 1284 template <typename To, typename From>
cannam@135 1285 To& downcast(From& from) {
cannam@135 1286 // Down-cast a value to a sub-type, asserting that the cast is valid. In opt mode this is a
cannam@135 1287 // static_cast, but in debug mode (when RTTI is enabled) a dynamic_cast will be used to verify
cannam@135 1288 // that the value really has the requested type.
cannam@135 1289
cannam@135 1290 // Force a compile error if To is not a subtype of From.
cannam@135 1291 if (false) {
cannam@135 1292 kj::implicitCast<From*>(kj::implicitCast<To*>(nullptr));
cannam@135 1293 }
cannam@135 1294
cannam@135 1295 #if !KJ_NO_RTTI
cannam@135 1296 KJ_IREQUIRE(dynamic_cast<To*>(&from) != nullptr, "Value cannot be downcast() to requested type.");
cannam@135 1297 #endif
cannam@135 1298
cannam@135 1299 return static_cast<To&>(from);
cannam@135 1300 }
cannam@135 1301
cannam@135 1302 // =======================================================================================
cannam@135 1303 // Defer
cannam@135 1304
cannam@135 1305 namespace _ { // private
cannam@135 1306
cannam@135 1307 template <typename Func>
cannam@135 1308 class Deferred {
cannam@135 1309 public:
cannam@135 1310 inline Deferred(Func&& func): func(kj::fwd<Func>(func)), canceled(false) {}
cannam@135 1311 inline ~Deferred() noexcept(false) { if (!canceled) func(); }
cannam@135 1312 KJ_DISALLOW_COPY(Deferred);
cannam@135 1313
cannam@135 1314 // This move constructor is usually optimized away by the compiler.
cannam@135 1315 inline Deferred(Deferred&& other): func(kj::mv(other.func)), canceled(false) {
cannam@135 1316 other.canceled = true;
cannam@135 1317 }
cannam@135 1318 private:
cannam@135 1319 Func func;
cannam@135 1320 bool canceled;
cannam@135 1321 };
cannam@135 1322
cannam@135 1323 } // namespace _ (private)
cannam@135 1324
cannam@135 1325 template <typename Func>
cannam@135 1326 _::Deferred<Func> defer(Func&& func) {
cannam@135 1327 // Returns an object which will invoke the given functor in its destructor. The object is not
cannam@135 1328 // copyable but is movable with the semantics you'd expect. Since the return type is private,
cannam@135 1329 // you need to assign to an `auto` variable.
cannam@135 1330 //
cannam@135 1331 // The KJ_DEFER macro provides slightly more convenient syntax for the common case where you
cannam@135 1332 // want some code to run at current scope exit.
cannam@135 1333
cannam@135 1334 return _::Deferred<Func>(kj::fwd<Func>(func));
cannam@135 1335 }
cannam@135 1336
cannam@135 1337 #define KJ_DEFER(code) auto KJ_UNIQUE_NAME(_kjDefer) = ::kj::defer([&](){code;})
cannam@135 1338 // Run the given code when the function exits, whether by return or exception.
cannam@135 1339
cannam@135 1340 } // namespace kj
cannam@135 1341
cannam@135 1342 #endif // KJ_COMMON_H_