annotate osx/include/kj/common.h @ 83:ae30d91d2ffe

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