annotate win32-mingw/include/kj/common.h @ 163:5cc1366da2e9

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