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