cannam@147: // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors cannam@147: // Licensed under the MIT License: cannam@147: // cannam@147: // Permission is hereby granted, free of charge, to any person obtaining a copy cannam@147: // of this software and associated documentation files (the "Software"), to deal cannam@147: // in the Software without restriction, including without limitation the rights cannam@147: // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell cannam@147: // copies of the Software, and to permit persons to whom the Software is cannam@147: // furnished to do so, subject to the following conditions: cannam@147: // cannam@147: // The above copyright notice and this permission notice shall be included in cannam@147: // all copies or substantial portions of the Software. cannam@147: // cannam@147: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR cannam@147: // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, cannam@147: // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE cannam@147: // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER cannam@147: // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, cannam@147: // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN cannam@147: // THE SOFTWARE. cannam@147: cannam@147: // Header that should be #included by everyone. cannam@147: // cannam@147: // This defines very simple utilities that are widely applicable. cannam@147: cannam@147: #ifndef KJ_COMMON_H_ cannam@147: #define KJ_COMMON_H_ cannam@147: cannam@147: #if defined(__GNUC__) && !KJ_HEADER_WARNINGS cannam@147: #pragma GCC system_header cannam@147: #endif cannam@147: cannam@147: #ifndef KJ_NO_COMPILER_CHECK cannam@147: #if __cplusplus < 201103L && !__CDT_PARSER__ && !_MSC_VER cannam@147: #error "This code requires C++11. Either your compiler does not support it or it is not enabled." cannam@147: #ifdef __GNUC__ cannam@147: // Compiler claims compatibility with GCC, so presumably supports -std. cannam@147: #error "Pass -std=c++11 on the compiler command line to enable C++11." cannam@147: #endif cannam@147: #endif cannam@147: cannam@147: #ifdef __GNUC__ cannam@147: #if __clang__ cannam@147: #if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2) cannam@147: #warning "This library requires at least Clang 3.2." cannam@147: #elif defined(__apple_build_version__) && __apple_build_version__ <= 4250028 cannam@147: #warning "This library requires at least Clang 3.2. XCode 4.6's Clang, which claims to be "\ cannam@147: "version 4.2 (wat?), is actually built from some random SVN revision between 3.1 "\ cannam@147: "and 3.2. Unfortunately, it is insufficient for compiling this library. You can "\ cannam@147: "download the real Clang 3.2 (or newer) from the Clang web site. Step-by-step "\ cannam@147: "instructions can be found in Cap'n Proto's documentation: "\ cannam@147: "http://kentonv.github.io/capnproto/install.html#clang_32_on_mac_osx" cannam@147: #elif __cplusplus >= 201103L && !__has_include() cannam@147: #warning "Your compiler supports C++11 but your C++ standard library does not. If your "\ cannam@147: "system has libc++ installed (as should be the case on e.g. Mac OSX), try adding "\ cannam@147: "-stdlib=libc++ to your CXXFLAGS." cannam@147: #endif cannam@147: #else cannam@147: #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) cannam@147: #warning "This library requires at least GCC 4.7." cannam@147: #endif cannam@147: #endif cannam@147: #elif defined(_MSC_VER) cannam@147: #if _MSC_VER < 1900 cannam@147: #error "You need Visual Studio 2015 or better to compile this code." cannam@147: #endif cannam@147: #else cannam@147: #warning "I don't recognize your compiler. As of this writing, Clang and GCC are the only "\ cannam@147: "known compilers with enough C++11 support for this library. "\ cannam@147: "#define KJ_NO_COMPILER_CHECK to make this warning go away." cannam@147: #endif cannam@147: #endif cannam@147: cannam@147: #include cannam@147: #include cannam@147: cannam@147: #if __linux__ && __cplusplus > 201200L cannam@147: // Hack around stdlib bug with C++14 that exists on some Linux systems. cannam@147: // Apparently in this mode the C library decides not to define gets() but the C++ library still cannam@147: // tries to import it into the std namespace. This bug has been fixed at the source but is still cannam@147: // widely present in the wild e.g. on Ubuntu 14.04. cannam@147: #undef _GLIBCXX_HAVE_GETS cannam@147: #endif cannam@147: cannam@147: #if defined(_MSC_VER) cannam@147: #ifndef NOMINMAX cannam@147: #define NOMINMAX 1 cannam@147: #endif cannam@147: #include // __popcnt cannam@147: #endif cannam@147: cannam@147: // ======================================================================================= cannam@147: cannam@147: namespace kj { cannam@147: cannam@147: typedef unsigned int uint; cannam@147: typedef unsigned char byte; cannam@147: cannam@147: // ======================================================================================= cannam@147: // Common macros, especially for common yet compiler-specific features. cannam@147: cannam@147: // Detect whether RTTI and exceptions are enabled, assuming they are unless we have specific cannam@147: // evidence to the contrary. Clients can always define KJ_NO_RTTI or KJ_NO_EXCEPTIONS explicitly cannam@147: // to override these checks. cannam@147: #ifdef __GNUC__ cannam@147: #if !defined(KJ_NO_RTTI) && !__GXX_RTTI cannam@147: #define KJ_NO_RTTI 1 cannam@147: #endif cannam@147: #if !defined(KJ_NO_EXCEPTIONS) && !__EXCEPTIONS cannam@147: #define KJ_NO_EXCEPTIONS 1 cannam@147: #endif cannam@147: #elif defined(_MSC_VER) cannam@147: #if !defined(KJ_NO_RTTI) && !defined(_CPPRTTI) cannam@147: #define KJ_NO_RTTI 1 cannam@147: #endif cannam@147: #if !defined(KJ_NO_EXCEPTIONS) && !defined(_CPPUNWIND) cannam@147: #define KJ_NO_EXCEPTIONS 1 cannam@147: #endif cannam@147: #endif cannam@147: cannam@147: #if !defined(KJ_DEBUG) && !defined(KJ_NDEBUG) cannam@147: // Heuristically decide whether to enable debug mode. If DEBUG or NDEBUG is defined, use that. cannam@147: // Otherwise, fall back to checking whether optimization is enabled. cannam@147: #if defined(DEBUG) || defined(_DEBUG) cannam@147: #define KJ_DEBUG cannam@147: #elif defined(NDEBUG) cannam@147: #define KJ_NDEBUG cannam@147: #elif __OPTIMIZE__ cannam@147: #define KJ_NDEBUG cannam@147: #else cannam@147: #define KJ_DEBUG cannam@147: #endif cannam@147: #endif cannam@147: cannam@147: #define KJ_DISALLOW_COPY(classname) \ cannam@147: classname(const classname&) = delete; \ cannam@147: classname& operator=(const classname&) = delete cannam@147: // Deletes the implicit copy constructor and assignment operator. cannam@147: cannam@147: #ifdef __GNUC__ cannam@147: #define KJ_LIKELY(condition) __builtin_expect(condition, true) cannam@147: #define KJ_UNLIKELY(condition) __builtin_expect(condition, false) cannam@147: // Branch prediction macros. Evaluates to the condition given, but also tells the compiler that we cannam@147: // expect the condition to be true/false enough of the time that it's worth hard-coding branch cannam@147: // prediction. cannam@147: #else cannam@147: #define KJ_LIKELY(condition) (condition) cannam@147: #define KJ_UNLIKELY(condition) (condition) cannam@147: #endif cannam@147: cannam@147: #if defined(KJ_DEBUG) || __NO_INLINE__ cannam@147: #define KJ_ALWAYS_INLINE(...) inline __VA_ARGS__ cannam@147: // Don't force inline in debug mode. cannam@147: #else cannam@147: #if defined(_MSC_VER) cannam@147: #define KJ_ALWAYS_INLINE(...) __forceinline __VA_ARGS__ cannam@147: #else cannam@147: #define KJ_ALWAYS_INLINE(...) inline __VA_ARGS__ __attribute__((always_inline)) cannam@147: #endif cannam@147: // Force a function to always be inlined. Apply only to the prototype, not to the definition. cannam@147: #endif cannam@147: cannam@147: #if defined(_MSC_VER) cannam@147: #define KJ_NOINLINE __declspec(noinline) cannam@147: #else cannam@147: #define KJ_NOINLINE __attribute__((noinline)) cannam@147: #endif cannam@147: cannam@147: #if defined(_MSC_VER) cannam@147: #define KJ_NORETURN(prototype) __declspec(noreturn) prototype cannam@147: #define KJ_UNUSED cannam@147: #define KJ_WARN_UNUSED_RESULT cannam@147: // TODO(msvc): KJ_WARN_UNUSED_RESULT can use _Check_return_ on MSVC, but it's a prefix, so cannam@147: // wrapping the whole prototype is needed. http://msdn.microsoft.com/en-us/library/jj159529.aspx cannam@147: // Similarly, KJ_UNUSED could use __pragma(warning(suppress:...)), but again that's a prefix. cannam@147: #else cannam@147: #define KJ_NORETURN(prototype) prototype __attribute__((noreturn)) cannam@147: #define KJ_UNUSED __attribute__((unused)) cannam@147: #define KJ_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) cannam@147: #endif cannam@147: cannam@147: #if __clang__ cannam@147: #define KJ_UNUSED_MEMBER __attribute__((unused)) cannam@147: // Inhibits "unused" warning for member variables. Only Clang produces such a warning, while GCC cannam@147: // complains if the attribute is set on members. cannam@147: #else cannam@147: #define KJ_UNUSED_MEMBER cannam@147: #endif cannam@147: cannam@147: #if __clang__ cannam@147: #define KJ_DEPRECATED(reason) \ cannam@147: __attribute__((deprecated(reason))) cannam@147: #define KJ_UNAVAILABLE(reason) \ cannam@147: __attribute__((unavailable(reason))) cannam@147: #elif __GNUC__ cannam@147: #define KJ_DEPRECATED(reason) \ cannam@147: __attribute__((deprecated)) cannam@147: #define KJ_UNAVAILABLE(reason) cannam@147: #else cannam@147: #define KJ_DEPRECATED(reason) cannam@147: #define KJ_UNAVAILABLE(reason) cannam@147: // TODO(msvc): Again, here, MSVC prefers a prefix, __declspec(deprecated). cannam@147: #endif cannam@147: cannam@147: namespace _ { // private cannam@147: cannam@147: KJ_NORETURN(void inlineRequireFailure( cannam@147: const char* file, int line, const char* expectation, const char* macroArgs, cannam@147: const char* message = nullptr)); cannam@147: cannam@147: KJ_NORETURN(void unreachable()); cannam@147: cannam@147: } // namespace _ (private) cannam@147: cannam@147: #ifdef KJ_DEBUG cannam@147: #if _MSC_VER cannam@147: #define KJ_IREQUIRE(condition, ...) \ cannam@147: if (KJ_LIKELY(condition)); else ::kj::_::inlineRequireFailure( \ cannam@147: __FILE__, __LINE__, #condition, "" #__VA_ARGS__, __VA_ARGS__) cannam@147: // Version of KJ_DREQUIRE() which is safe to use in headers that are #included by users. Used to cannam@147: // check preconditions inside inline methods. KJ_IREQUIRE is particularly useful in that cannam@147: // it will be enabled depending on whether the application is compiled in debug mode rather than cannam@147: // whether libkj is. cannam@147: #else cannam@147: #define KJ_IREQUIRE(condition, ...) \ cannam@147: if (KJ_LIKELY(condition)); else ::kj::_::inlineRequireFailure( \ cannam@147: __FILE__, __LINE__, #condition, #__VA_ARGS__, ##__VA_ARGS__) cannam@147: // Version of KJ_DREQUIRE() which is safe to use in headers that are #included by users. Used to cannam@147: // check preconditions inside inline methods. KJ_IREQUIRE is particularly useful in that cannam@147: // it will be enabled depending on whether the application is compiled in debug mode rather than cannam@147: // whether libkj is. cannam@147: #endif cannam@147: #else cannam@147: #define KJ_IREQUIRE(condition, ...) cannam@147: #endif cannam@147: cannam@147: #define KJ_IASSERT KJ_IREQUIRE cannam@147: cannam@147: #define KJ_UNREACHABLE ::kj::_::unreachable(); cannam@147: // Put this on code paths that cannot be reached to suppress compiler warnings about missing cannam@147: // returns. cannam@147: cannam@147: #if __clang__ cannam@147: #define KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT cannam@147: #else cannam@147: #define KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT KJ_UNREACHABLE cannam@147: #endif cannam@147: cannam@147: // #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack) cannam@147: // cannam@147: // Allocate an array, preferably on the stack, unless it is too big. On GCC this will use cannam@147: // variable-sized arrays. For other compilers we could just use a fixed-size array. `minStack` cannam@147: // is the stack array size to use if variable-width arrays are not supported. `maxStack` is the cannam@147: // maximum stack array size if variable-width arrays *are* supported. cannam@147: #if __GNUC__ && !__clang__ cannam@147: #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack) \ cannam@147: size_t name##_size = (size); \ cannam@147: bool name##_isOnStack = name##_size <= (maxStack); \ cannam@147: type name##_stack[name##_isOnStack ? size : 0]; \ cannam@147: ::kj::Array name##_heap = name##_isOnStack ? \ cannam@147: nullptr : kj::heapArray(name##_size); \ cannam@147: ::kj::ArrayPtr name = name##_isOnStack ? \ cannam@147: kj::arrayPtr(name##_stack, name##_size) : name##_heap cannam@147: #else cannam@147: #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack) \ cannam@147: size_t name##_size = (size); \ cannam@147: bool name##_isOnStack = name##_size <= (minStack); \ cannam@147: type name##_stack[minStack]; \ cannam@147: ::kj::Array name##_heap = name##_isOnStack ? \ cannam@147: nullptr : kj::heapArray(name##_size); \ cannam@147: ::kj::ArrayPtr name = name##_isOnStack ? \ cannam@147: kj::arrayPtr(name##_stack, name##_size) : name##_heap cannam@147: #endif cannam@147: cannam@147: #define KJ_CONCAT_(x, y) x##y cannam@147: #define KJ_CONCAT(x, y) KJ_CONCAT_(x, y) cannam@147: #define KJ_UNIQUE_NAME(prefix) KJ_CONCAT(prefix, __LINE__) cannam@147: // Create a unique identifier name. We use concatenate __LINE__ rather than __COUNTER__ so that cannam@147: // the name can be used multiple times in the same macro. cannam@147: cannam@147: #if _MSC_VER cannam@147: cannam@147: #define KJ_CONSTEXPR(...) __VA_ARGS__ cannam@147: // Use in cases where MSVC barfs on constexpr. A replacement keyword (e.g. "const") can be cannam@147: // provided, or just leave blank to remove the keyword entirely. cannam@147: // cannam@147: // TODO(msvc): Remove this hack once MSVC fully supports constexpr. cannam@147: cannam@147: #ifndef __restrict__ cannam@147: #define __restrict__ __restrict cannam@147: // TODO(msvc): Would it be better to define a KJ_RESTRICT macro? cannam@147: #endif cannam@147: cannam@147: #pragma warning(disable: 4521 4522) cannam@147: // This warning complains when there are two copy constructors, one for a const reference and cannam@147: // one for a non-const reference. It is often quite necessary to do this in wrapper templates, cannam@147: // therefore this warning is dumb and we disable it. cannam@147: cannam@147: #pragma warning(disable: 4458) cannam@147: // Warns when a parameter name shadows a class member. Unfortunately my code does this a lot, cannam@147: // since I don't use a special name format for members. cannam@147: cannam@147: #else // _MSC_VER cannam@147: #define KJ_CONSTEXPR(...) constexpr cannam@147: #endif cannam@147: cannam@147: // ======================================================================================= cannam@147: // Template metaprogramming helpers. cannam@147: cannam@147: template struct NoInfer_ { typedef T Type; }; cannam@147: template using NoInfer = typename NoInfer_::Type; cannam@147: // Use NoInfer::Type in place of T for a template function parameter to prevent inference of cannam@147: // the type based on the parameter value. cannam@147: cannam@147: template struct RemoveConst_ { typedef T Type; }; cannam@147: template struct RemoveConst_ { typedef T Type; }; cannam@147: template using RemoveConst = typename RemoveConst_::Type; cannam@147: cannam@147: template struct IsLvalueReference_ { static constexpr bool value = false; }; cannam@147: template struct IsLvalueReference_ { static constexpr bool value = true; }; cannam@147: template cannam@147: inline constexpr bool isLvalueReference() { return IsLvalueReference_::value; } cannam@147: cannam@147: template struct Decay_ { typedef T Type; }; cannam@147: template struct Decay_ { typedef typename Decay_::Type Type; }; cannam@147: template struct Decay_ { typedef typename Decay_::Type Type; }; cannam@147: template struct Decay_ { typedef typename Decay_::Type Type; }; cannam@147: template struct Decay_ { typedef typename Decay_::Type Type; }; cannam@147: template struct Decay_ { typedef typename Decay_::Type Type; }; cannam@147: template struct Decay_ { typedef typename Decay_::Type Type; }; cannam@147: template struct Decay_ { typedef typename Decay_::Type Type; }; cannam@147: template struct Decay_ { typedef typename Decay_::Type Type; }; cannam@147: template using Decay = typename Decay_::Type; cannam@147: cannam@147: template struct EnableIf_; cannam@147: template <> struct EnableIf_ { typedef void Type; }; cannam@147: template using EnableIf = typename EnableIf_::Type; cannam@147: // Use like: cannam@147: // cannam@147: // template ()> cannam@147: // void func(T&& t); cannam@147: cannam@147: template struct VoidSfinae_ { using Type = void; }; cannam@147: template using VoidSfinae = typename VoidSfinae_::Type; cannam@147: // Note: VoidSfinae is std::void_t from C++17. cannam@147: cannam@147: template cannam@147: T instance() noexcept; cannam@147: // Like std::declval, but doesn't transform T into an rvalue reference. If you want that, specify cannam@147: // instance(). cannam@147: cannam@147: struct DisallowConstCopy { cannam@147: // Inherit from this, or declare a member variable of this type, to prevent the class from being cannam@147: // copyable from a const reference -- instead, it will only be copyable from non-const references. cannam@147: // This is useful for enforcing transitive constness of contained pointers. cannam@147: // cannam@147: // For example, say you have a type T which contains a pointer. T has non-const methods which cannam@147: // modify the value at that pointer, but T's const methods are designed to allow reading only. cannam@147: // Unfortunately, if T has a regular copy constructor, someone can simply make a copy of T and cannam@147: // then use it to modify the pointed-to value. However, if T inherits DisallowConstCopy, then cannam@147: // callers will only be able to copy non-const instances of T. Ideally, there is some cannam@147: // parallel type ImmutableT which is like a version of T that only has const methods, and can cannam@147: // be copied from a const T. cannam@147: // cannam@147: // Note that due to C++ rules about implicit copy constructors and assignment operators, any cannam@147: // type that contains or inherits from a type that disallows const copies will also automatically cannam@147: // disallow const copies. Hey, cool, that's exactly what we want. cannam@147: cannam@147: #if CAPNP_DEBUG_TYPES cannam@147: // Alas! Declaring a defaulted non-const copy constructor tickles a bug which causes GCC and cannam@147: // Clang to disagree on ABI, using different calling conventions to pass this type, leading to cannam@147: // immediate segfaults. See: cannam@147: // https://bugs.llvm.org/show_bug.cgi?id=23764 cannam@147: // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58074 cannam@147: // cannam@147: // Because of this, we can't use this technique. We guard it by CAPNP_DEBUG_TYPES so that it cannam@147: // still applies to the Cap'n Proto developers during internal testing. cannam@147: cannam@147: DisallowConstCopy() = default; cannam@147: DisallowConstCopy(DisallowConstCopy&) = default; cannam@147: DisallowConstCopy(DisallowConstCopy&&) = default; cannam@147: DisallowConstCopy& operator=(DisallowConstCopy&) = default; cannam@147: DisallowConstCopy& operator=(DisallowConstCopy&&) = default; cannam@147: #endif cannam@147: }; cannam@147: cannam@147: #if _MSC_VER cannam@147: cannam@147: #define KJ_CPCAP(obj) obj=::kj::cp(obj) cannam@147: // TODO(msvc): MSVC refuses to invoke non-const versions of copy constructors in by-value lambda cannam@147: // captures. Wrap your captured object in this macro to force the compiler to perform a copy. cannam@147: // Example: cannam@147: // cannam@147: // struct Foo: DisallowConstCopy {}; cannam@147: // Foo foo; cannam@147: // auto lambda = [KJ_CPCAP(foo)] {}; cannam@147: cannam@147: #else cannam@147: cannam@147: #define KJ_CPCAP(obj) obj cannam@147: // Clang and gcc both already perform copy capturing correctly with non-const copy constructors. cannam@147: cannam@147: #endif cannam@147: cannam@147: template cannam@147: struct DisallowConstCopyIfNotConst: public DisallowConstCopy { cannam@147: // Inherit from this when implementing a template that contains a pointer to T and which should cannam@147: // enforce transitive constness. If T is a const type, this has no effect. Otherwise, it is cannam@147: // an alias for DisallowConstCopy. cannam@147: }; cannam@147: cannam@147: template cannam@147: struct DisallowConstCopyIfNotConst {}; cannam@147: cannam@147: template struct IsConst_ { static constexpr bool value = false; }; cannam@147: template struct IsConst_ { static constexpr bool value = true; }; cannam@147: template constexpr bool isConst() { return IsConst_::value; } cannam@147: cannam@147: template struct EnableIfNotConst_ { typedef T Type; }; cannam@147: template struct EnableIfNotConst_; cannam@147: template using EnableIfNotConst = typename EnableIfNotConst_::Type; cannam@147: cannam@147: template struct EnableIfConst_; cannam@147: template struct EnableIfConst_ { typedef T Type; }; cannam@147: template using EnableIfConst = typename EnableIfConst_::Type; cannam@147: cannam@147: template struct RemoveConstOrDisable_ { struct Type; }; cannam@147: template struct RemoveConstOrDisable_ { typedef T Type; }; cannam@147: template using RemoveConstOrDisable = typename RemoveConstOrDisable_::Type; cannam@147: cannam@147: template struct IsReference_ { static constexpr bool value = false; }; cannam@147: template struct IsReference_ { static constexpr bool value = true; }; cannam@147: template constexpr bool isReference() { return IsReference_::value; } cannam@147: cannam@147: template cannam@147: struct PropagateConst_ { typedef To Type; }; cannam@147: template cannam@147: struct PropagateConst_ { typedef const To Type; }; cannam@147: template cannam@147: using PropagateConst = typename PropagateConst_::Type; cannam@147: cannam@147: namespace _ { // private cannam@147: cannam@147: template cannam@147: T refIfLvalue(T&&); cannam@147: cannam@147: } // namespace _ (private) cannam@147: cannam@147: #define KJ_DECLTYPE_REF(exp) decltype(::kj::_::refIfLvalue(exp)) cannam@147: // Like decltype(exp), but if exp is an lvalue, produces a reference type. cannam@147: // cannam@147: // int i; cannam@147: // decltype(i) i1(i); // i1 has type int. cannam@147: // KJ_DECLTYPE_REF(i + 1) i2(i + 1); // i2 has type int. cannam@147: // KJ_DECLTYPE_REF(i) i3(i); // i3 has type int&. cannam@147: // KJ_DECLTYPE_REF(kj::mv(i)) i4(kj::mv(i)); // i4 has type int. cannam@147: cannam@147: template cannam@147: struct CanConvert_ { cannam@147: static int sfinae(T); cannam@147: static bool sfinae(...); cannam@147: }; cannam@147: cannam@147: template cannam@147: constexpr bool canConvert() { cannam@147: return sizeof(CanConvert_::sfinae(instance())) == sizeof(int); cannam@147: } cannam@147: cannam@147: #if __GNUC__ && !__clang__ && __GNUC__ < 5 cannam@147: template cannam@147: constexpr bool canMemcpy() { cannam@147: // Returns true if T can be copied using memcpy instead of using the copy constructor or cannam@147: // assignment operator. cannam@147: cannam@147: // GCC 4 does not have __is_trivially_constructible and friends, and there doesn't seem to be cannam@147: // any reliable alternative. __has_trivial_copy() and __has_trivial_assign() return the right cannam@147: // thing at one point but later on they changed such that a deleted copy constructor was cannam@147: // considered "trivial" (apparently technically correct, though useless). So, on GCC 4 we give up cannam@147: // and assume we can't memcpy() at all, and must explicitly copy-construct everything. cannam@147: return false; cannam@147: } cannam@147: #define KJ_ASSERT_CAN_MEMCPY(T) cannam@147: #else cannam@147: template cannam@147: constexpr bool canMemcpy() { cannam@147: // Returns true if T can be copied using memcpy instead of using the copy constructor or cannam@147: // assignment operator. cannam@147: cannam@147: return __is_trivially_constructible(T, const T&) && __is_trivially_assignable(T, const T&); cannam@147: } cannam@147: #define KJ_ASSERT_CAN_MEMCPY(T) \ cannam@147: static_assert(kj::canMemcpy(), "this code expects this type to be memcpy()-able"); cannam@147: #endif cannam@147: cannam@147: // ======================================================================================= cannam@147: // Equivalents to std::move() and std::forward(), since these are very commonly needed and the cannam@147: // std header pulls in lots of other stuff. cannam@147: // cannam@147: // We use abbreviated names mv and fwd because these helpers (especially mv) are so commonly used cannam@147: // that the cost of typing more letters outweighs the cost of being slightly harder to understand cannam@147: // when first encountered. cannam@147: cannam@147: template constexpr T&& mv(T& t) noexcept { return static_cast(t); } cannam@147: template constexpr T&& fwd(NoInfer& t) noexcept { return static_cast(t); } cannam@147: cannam@147: template constexpr T cp(T& t) noexcept { return t; } cannam@147: template constexpr T cp(const T& t) noexcept { return t; } cannam@147: // Useful to force a copy, particularly to pass into a function that expects T&&. cannam@147: cannam@147: template struct ChooseType_; cannam@147: template struct ChooseType_ { typedef T Type; }; cannam@147: template struct ChooseType_ { typedef T Type; }; cannam@147: template struct ChooseType_ { typedef U Type; }; cannam@147: cannam@147: template cannam@147: using WiderType = typename ChooseType_= sizeof(U)>::Type; cannam@147: cannam@147: template cannam@147: inline constexpr auto min(T&& a, U&& b) -> WiderType, Decay> { cannam@147: return a < b ? WiderType, Decay>(a) : WiderType, Decay>(b); cannam@147: } cannam@147: cannam@147: template cannam@147: inline constexpr auto max(T&& a, U&& b) -> WiderType, Decay> { cannam@147: return a > b ? WiderType, Decay>(a) : WiderType, Decay>(b); cannam@147: } cannam@147: cannam@147: template cannam@147: inline constexpr size_t size(T (&arr)[s]) { return s; } cannam@147: template cannam@147: inline constexpr size_t size(T&& arr) { return arr.size(); } cannam@147: // Returns the size of the parameter, whether the parameter is a regular C array or a container cannam@147: // with a `.size()` method. cannam@147: cannam@147: class MaxValue_ { cannam@147: private: cannam@147: template cannam@147: inline constexpr T maxSigned() const { cannam@147: return (1ull << (sizeof(T) * 8 - 1)) - 1; cannam@147: } cannam@147: template cannam@147: inline constexpr T maxUnsigned() const { cannam@147: return ~static_cast(0u); cannam@147: } cannam@147: cannam@147: public: cannam@147: #define _kJ_HANDLE_TYPE(T) \ cannam@147: inline constexpr operator signed T() const { return MaxValue_::maxSigned < signed T>(); } \ cannam@147: inline constexpr operator unsigned T() const { return MaxValue_::maxUnsigned(); } cannam@147: _kJ_HANDLE_TYPE(char) cannam@147: _kJ_HANDLE_TYPE(short) cannam@147: _kJ_HANDLE_TYPE(int) cannam@147: _kJ_HANDLE_TYPE(long) cannam@147: _kJ_HANDLE_TYPE(long long) cannam@147: #undef _kJ_HANDLE_TYPE cannam@147: cannam@147: inline constexpr operator char() const { cannam@147: // `char` is different from both `signed char` and `unsigned char`, and may be signed or cannam@147: // unsigned on different platforms. Ugh. cannam@147: return char(-1) < 0 ? MaxValue_::maxSigned() cannam@147: : MaxValue_::maxUnsigned(); cannam@147: } cannam@147: }; cannam@147: cannam@147: class MinValue_ { cannam@147: private: cannam@147: template cannam@147: inline constexpr T minSigned() const { cannam@147: return 1ull << (sizeof(T) * 8 - 1); cannam@147: } cannam@147: template cannam@147: inline constexpr T minUnsigned() const { cannam@147: return 0u; cannam@147: } cannam@147: cannam@147: public: cannam@147: #define _kJ_HANDLE_TYPE(T) \ cannam@147: inline constexpr operator signed T() const { return MinValue_::minSigned < signed T>(); } \ cannam@147: inline constexpr operator unsigned T() const { return MinValue_::minUnsigned(); } cannam@147: _kJ_HANDLE_TYPE(char) cannam@147: _kJ_HANDLE_TYPE(short) cannam@147: _kJ_HANDLE_TYPE(int) cannam@147: _kJ_HANDLE_TYPE(long) cannam@147: _kJ_HANDLE_TYPE(long long) cannam@147: #undef _kJ_HANDLE_TYPE cannam@147: cannam@147: inline constexpr operator char() const { cannam@147: // `char` is different from both `signed char` and `unsigned char`, and may be signed or cannam@147: // unsigned on different platforms. Ugh. cannam@147: return char(-1) < 0 ? MinValue_::minSigned() cannam@147: : MinValue_::minUnsigned(); cannam@147: } cannam@147: }; cannam@147: cannam@147: static KJ_CONSTEXPR(const) MaxValue_ maxValue = MaxValue_(); cannam@147: // A special constant which, when cast to an integer type, takes on the maximum possible value of cannam@147: // that type. This is useful to use as e.g. a parameter to a function because it will be robust cannam@147: // in the face of changes to the parameter's type. cannam@147: // cannam@147: // `char` is not supported, but `signed char` and `unsigned char` are. cannam@147: cannam@147: static KJ_CONSTEXPR(const) MinValue_ minValue = MinValue_(); cannam@147: // A special constant which, when cast to an integer type, takes on the minimum possible value cannam@147: // of that type. This is useful to use as e.g. a parameter to a function because it will be robust cannam@147: // in the face of changes to the parameter's type. cannam@147: // cannam@147: // `char` is not supported, but `signed char` and `unsigned char` are. cannam@147: cannam@147: template cannam@147: inline bool operator==(T t, MaxValue_) { return t == Decay(maxValue); } cannam@147: template cannam@147: inline bool operator==(T t, MinValue_) { return t == Decay(minValue); } cannam@147: cannam@147: template cannam@147: inline constexpr unsigned long long maxValueForBits() { cannam@147: // Get the maximum integer representable in the given number of bits. cannam@147: cannam@147: // 1ull << 64 is unfortunately undefined. cannam@147: return (bits == 64 ? 0 : (1ull << bits)) - 1; cannam@147: } cannam@147: cannam@147: struct ThrowOverflow { cannam@147: // Functor which throws an exception complaining about integer overflow. Usually this is used cannam@147: // with the interfaces in units.h, but is defined here because Cap'n Proto wants to avoid cannam@147: // including units.h when not using CAPNP_DEBUG_TYPES. cannam@147: void operator()() const; cannam@147: }; cannam@147: cannam@147: #if __GNUC__ cannam@147: inline constexpr float inf() { return __builtin_huge_valf(); } cannam@147: inline constexpr float nan() { return __builtin_nanf(""); } cannam@147: cannam@147: #elif _MSC_VER cannam@147: cannam@147: // Do what MSVC math.h does cannam@147: #pragma warning(push) cannam@147: #pragma warning(disable: 4756) // "overflow in constant arithmetic" cannam@147: inline constexpr float inf() { return (float)(1e300 * 1e300); } cannam@147: #pragma warning(pop) cannam@147: cannam@147: float nan(); cannam@147: // Unfortunatley, inf() * 0.0f produces a NaN with the sign bit set, whereas our preferred cannam@147: // canonical NaN should not have the sign bit set. std::numeric_limits::quiet_NaN() cannam@147: // returns the correct NaN, but we don't want to #include that here. So, we give up and make cannam@147: // this out-of-line on MSVC. cannam@147: // cannam@147: // TODO(msvc): Can we do better? cannam@147: cannam@147: #else cannam@147: #error "Not sure how to support your compiler." cannam@147: #endif cannam@147: cannam@147: inline constexpr bool isNaN(float f) { return f != f; } cannam@147: inline constexpr bool isNaN(double f) { return f != f; } cannam@147: cannam@147: inline int popCount(unsigned int x) { cannam@147: #if defined(_MSC_VER) cannam@147: return __popcnt(x); cannam@147: // Note: __popcnt returns unsigned int, but the value is clearly guaranteed to fit into an int cannam@147: #else cannam@147: return __builtin_popcount(x); cannam@147: #endif cannam@147: } cannam@147: cannam@147: // ======================================================================================= cannam@147: // Useful fake containers cannam@147: cannam@147: template cannam@147: class Range { cannam@147: public: cannam@147: inline constexpr Range(const T& begin, const T& end): begin_(begin), end_(end) {} cannam@147: inline explicit constexpr Range(const T& end): begin_(0), end_(end) {} cannam@147: cannam@147: class Iterator { cannam@147: public: cannam@147: Iterator() = default; cannam@147: inline Iterator(const T& value): value(value) {} cannam@147: cannam@147: inline const T& operator* () const { return value; } cannam@147: inline const T& operator[](size_t index) const { return value + index; } cannam@147: inline Iterator& operator++() { ++value; return *this; } cannam@147: inline Iterator operator++(int) { return Iterator(value++); } cannam@147: inline Iterator& operator--() { --value; return *this; } cannam@147: inline Iterator operator--(int) { return Iterator(value--); } cannam@147: inline Iterator& operator+=(ptrdiff_t amount) { value += amount; return *this; } cannam@147: inline Iterator& operator-=(ptrdiff_t amount) { value -= amount; return *this; } cannam@147: inline Iterator operator+ (ptrdiff_t amount) const { return Iterator(value + amount); } cannam@147: inline Iterator operator- (ptrdiff_t amount) const { return Iterator(value - amount); } cannam@147: inline ptrdiff_t operator- (const Iterator& other) const { return value - other.value; } cannam@147: cannam@147: inline bool operator==(const Iterator& other) const { return value == other.value; } cannam@147: inline bool operator!=(const Iterator& other) const { return value != other.value; } cannam@147: inline bool operator<=(const Iterator& other) const { return value <= other.value; } cannam@147: inline bool operator>=(const Iterator& other) const { return value >= other.value; } cannam@147: inline bool operator< (const Iterator& other) const { return value < other.value; } cannam@147: inline bool operator> (const Iterator& other) const { return value > other.value; } cannam@147: cannam@147: private: cannam@147: T value; cannam@147: }; cannam@147: cannam@147: inline Iterator begin() const { return Iterator(begin_); } cannam@147: inline Iterator end() const { return Iterator(end_); } cannam@147: cannam@147: inline auto size() const -> decltype(instance() - instance()) { return end_ - begin_; } cannam@147: cannam@147: private: cannam@147: T begin_; cannam@147: T end_; cannam@147: }; cannam@147: cannam@147: template cannam@147: inline constexpr Range, Decay>> range(T begin, U end) { cannam@147: return Range, Decay>>(begin, end); cannam@147: } cannam@147: cannam@147: template cannam@147: inline constexpr Range> range(T begin, T end) { return Range>(begin, end); } cannam@147: // Returns a fake iterable container containing all values of T from `begin` (inclusive) to `end` cannam@147: // (exclusive). Example: cannam@147: // cannam@147: // // Prints 1, 2, 3, 4, 5, 6, 7, 8, 9. cannam@147: // for (int i: kj::range(1, 10)) { print(i); } cannam@147: cannam@147: template cannam@147: inline constexpr Range> zeroTo(T end) { return Range>(end); } cannam@147: // Returns a fake iterable container containing all values of T from zero (inclusive) to `end` cannam@147: // (exclusive). Example: cannam@147: // cannam@147: // // Prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. cannam@147: // for (int i: kj::zeroTo(10)) { print(i); } cannam@147: cannam@147: template cannam@147: inline constexpr Range indices(T&& container) { cannam@147: // Shortcut for iterating over the indices of a container: cannam@147: // cannam@147: // for (size_t i: kj::indices(myArray)) { handle(myArray[i]); } cannam@147: cannam@147: return range(0, kj::size(container)); cannam@147: } cannam@147: cannam@147: template cannam@147: class Repeat { cannam@147: public: cannam@147: inline constexpr Repeat(const T& value, size_t count): value(value), count(count) {} cannam@147: cannam@147: class Iterator { cannam@147: public: cannam@147: Iterator() = default; cannam@147: inline Iterator(const T& value, size_t index): value(value), index(index) {} cannam@147: cannam@147: inline const T& operator* () const { return value; } cannam@147: inline const T& operator[](ptrdiff_t index) const { return value; } cannam@147: inline Iterator& operator++() { ++index; return *this; } cannam@147: inline Iterator operator++(int) { return Iterator(value, index++); } cannam@147: inline Iterator& operator--() { --index; return *this; } cannam@147: inline Iterator operator--(int) { return Iterator(value, index--); } cannam@147: inline Iterator& operator+=(ptrdiff_t amount) { index += amount; return *this; } cannam@147: inline Iterator& operator-=(ptrdiff_t amount) { index -= amount; return *this; } cannam@147: inline Iterator operator+ (ptrdiff_t amount) const { return Iterator(value, index + amount); } cannam@147: inline Iterator operator- (ptrdiff_t amount) const { return Iterator(value, index - amount); } cannam@147: inline ptrdiff_t operator- (const Iterator& other) const { return index - other.index; } cannam@147: cannam@147: inline bool operator==(const Iterator& other) const { return index == other.index; } cannam@147: inline bool operator!=(const Iterator& other) const { return index != other.index; } cannam@147: inline bool operator<=(const Iterator& other) const { return index <= other.index; } cannam@147: inline bool operator>=(const Iterator& other) const { return index >= other.index; } cannam@147: inline bool operator< (const Iterator& other) const { return index < other.index; } cannam@147: inline bool operator> (const Iterator& other) const { return index > other.index; } cannam@147: cannam@147: private: cannam@147: T value; cannam@147: size_t index; cannam@147: }; cannam@147: cannam@147: inline Iterator begin() const { return Iterator(value, 0); } cannam@147: inline Iterator end() const { return Iterator(value, count); } cannam@147: cannam@147: inline size_t size() const { return count; } cannam@147: inline const T& operator[](ptrdiff_t) const { return value; } cannam@147: cannam@147: private: cannam@147: T value; cannam@147: size_t count; cannam@147: }; cannam@147: cannam@147: template cannam@147: inline constexpr Repeat> repeat(T&& value, size_t count) { cannam@147: // Returns a fake iterable which contains `count` repeats of `value`. Useful for e.g. creating cannam@147: // a bunch of spaces: `kj::repeat(' ', indent * 2)` cannam@147: cannam@147: return Repeat>(value, count); cannam@147: } cannam@147: cannam@147: // ======================================================================================= cannam@147: // Manually invoking constructors and destructors cannam@147: // cannam@147: // ctor(x, ...) and dtor(x) invoke x's constructor or destructor, respectively. cannam@147: cannam@147: // We want placement new, but we don't want to #include . operator new cannot be defined in cannam@147: // a namespace, and defining it globally conflicts with the definition in . So we have to cannam@147: // define a dummy type and an operator new that uses it. cannam@147: cannam@147: namespace _ { // private cannam@147: struct PlacementNew {}; cannam@147: } // namespace _ (private) cannam@147: } // namespace kj cannam@147: cannam@147: inline void* operator new(size_t, kj::_::PlacementNew, void* __p) noexcept { cannam@147: return __p; cannam@147: } cannam@147: cannam@147: inline void operator delete(void*, kj::_::PlacementNew, void* __p) noexcept {} cannam@147: cannam@147: namespace kj { cannam@147: cannam@147: template cannam@147: inline void ctor(T& location, Params&&... params) { cannam@147: new (_::PlacementNew(), &location) T(kj::fwd(params)...); cannam@147: } cannam@147: cannam@147: template cannam@147: inline void dtor(T& location) { cannam@147: location.~T(); cannam@147: } cannam@147: cannam@147: // ======================================================================================= cannam@147: // Maybe cannam@147: // cannam@147: // Use in cases where you want to indicate that a value may be null. Using Maybe instead of T* cannam@147: // forces the caller to handle the null case in order to satisfy the compiler, thus reliably cannam@147: // preventing null pointer dereferences at runtime. cannam@147: // cannam@147: // Maybe can be implicitly constructed from T and from nullptr. Additionally, it can be cannam@147: // implicitly constructed from T*, in which case the pointer is checked for nullness at runtime. cannam@147: // To read the value of a Maybe, do: cannam@147: // cannam@147: // KJ_IF_MAYBE(value, someFuncReturningMaybe()) { cannam@147: // doSomething(*value); cannam@147: // } else { cannam@147: // maybeWasNull(); cannam@147: // } cannam@147: // cannam@147: // KJ_IF_MAYBE's first parameter is a variable name which will be defined within the following cannam@147: // block. The variable will behave like a (guaranteed non-null) pointer to the Maybe's value, cannam@147: // though it may or may not actually be a pointer. cannam@147: // cannam@147: // Note that Maybe actually just wraps a pointer, whereas Maybe wraps a T and a boolean cannam@147: // indicating nullness. cannam@147: cannam@147: template cannam@147: class Maybe; cannam@147: cannam@147: namespace _ { // private cannam@147: cannam@147: template cannam@147: class NullableValue { cannam@147: // Class whose interface behaves much like T*, but actually contains an instance of T and a cannam@147: // boolean flag indicating nullness. cannam@147: cannam@147: public: cannam@147: inline NullableValue(NullableValue&& other) noexcept(noexcept(T(instance()))) cannam@147: : isSet(other.isSet) { cannam@147: if (isSet) { cannam@147: ctor(value, kj::mv(other.value)); cannam@147: } cannam@147: } cannam@147: inline NullableValue(const NullableValue& other) cannam@147: : isSet(other.isSet) { cannam@147: if (isSet) { cannam@147: ctor(value, other.value); cannam@147: } cannam@147: } cannam@147: inline NullableValue(NullableValue& other) cannam@147: : isSet(other.isSet) { cannam@147: if (isSet) { cannam@147: ctor(value, other.value); cannam@147: } cannam@147: } cannam@147: inline ~NullableValue() cannam@147: #if _MSC_VER cannam@147: // TODO(msvc): MSVC has a hard time with noexcept specifier expressions that are more complex cannam@147: // than `true` or `false`. We had a workaround for VS2015, but VS2017 regressed. cannam@147: noexcept(false) cannam@147: #else cannam@147: noexcept(noexcept(instance().~T())) cannam@147: #endif cannam@147: { cannam@147: if (isSet) { cannam@147: dtor(value); cannam@147: } cannam@147: } cannam@147: cannam@147: inline T& operator*() & { return value; } cannam@147: inline const T& operator*() const & { return value; } cannam@147: inline T&& operator*() && { return kj::mv(value); } cannam@147: inline const T&& operator*() const && { return kj::mv(value); } cannam@147: inline T* operator->() { return &value; } cannam@147: inline const T* operator->() const { return &value; } cannam@147: inline operator T*() { return isSet ? &value : nullptr; } cannam@147: inline operator const T*() const { return isSet ? &value : nullptr; } cannam@147: cannam@147: template cannam@147: inline T& emplace(Params&&... params) { cannam@147: if (isSet) { cannam@147: isSet = false; cannam@147: dtor(value); cannam@147: } cannam@147: ctor(value, kj::fwd(params)...); cannam@147: isSet = true; cannam@147: return value; cannam@147: } cannam@147: cannam@147: private: // internal interface used by friends only cannam@147: inline NullableValue() noexcept: isSet(false) {} cannam@147: inline NullableValue(T&& t) noexcept(noexcept(T(instance()))) cannam@147: : isSet(true) { cannam@147: ctor(value, kj::mv(t)); cannam@147: } cannam@147: inline NullableValue(T& t) cannam@147: : isSet(true) { cannam@147: ctor(value, t); cannam@147: } cannam@147: inline NullableValue(const T& t) cannam@147: : isSet(true) { cannam@147: ctor(value, t); cannam@147: } cannam@147: inline NullableValue(const T* t) cannam@147: : isSet(t != nullptr) { cannam@147: if (isSet) ctor(value, *t); cannam@147: } cannam@147: template cannam@147: inline NullableValue(NullableValue&& other) noexcept(noexcept(T(instance()))) cannam@147: : isSet(other.isSet) { cannam@147: if (isSet) { cannam@147: ctor(value, kj::mv(other.value)); cannam@147: } cannam@147: } cannam@147: template cannam@147: inline NullableValue(const NullableValue& other) cannam@147: : isSet(other.isSet) { cannam@147: if (isSet) { cannam@147: ctor(value, other.value); cannam@147: } cannam@147: } cannam@147: template cannam@147: inline NullableValue(const NullableValue& other) cannam@147: : isSet(other.isSet) { cannam@147: if (isSet) { cannam@147: ctor(value, *other.ptr); cannam@147: } cannam@147: } cannam@147: inline NullableValue(decltype(nullptr)): isSet(false) {} cannam@147: cannam@147: inline NullableValue& operator=(NullableValue&& other) { cannam@147: if (&other != this) { cannam@147: // Careful about throwing destructors/constructors here. cannam@147: if (isSet) { cannam@147: isSet = false; cannam@147: dtor(value); cannam@147: } cannam@147: if (other.isSet) { cannam@147: ctor(value, kj::mv(other.value)); cannam@147: isSet = true; cannam@147: } cannam@147: } cannam@147: return *this; cannam@147: } cannam@147: cannam@147: inline NullableValue& operator=(NullableValue& other) { cannam@147: if (&other != this) { cannam@147: // Careful about throwing destructors/constructors here. cannam@147: if (isSet) { cannam@147: isSet = false; cannam@147: dtor(value); cannam@147: } cannam@147: if (other.isSet) { cannam@147: ctor(value, other.value); cannam@147: isSet = true; cannam@147: } cannam@147: } cannam@147: return *this; cannam@147: } cannam@147: cannam@147: inline NullableValue& operator=(const NullableValue& other) { cannam@147: if (&other != this) { cannam@147: // Careful about throwing destructors/constructors here. cannam@147: if (isSet) { cannam@147: isSet = false; cannam@147: dtor(value); cannam@147: } cannam@147: if (other.isSet) { cannam@147: ctor(value, other.value); cannam@147: isSet = true; cannam@147: } cannam@147: } cannam@147: return *this; cannam@147: } cannam@147: cannam@147: inline bool operator==(decltype(nullptr)) const { return !isSet; } cannam@147: inline bool operator!=(decltype(nullptr)) const { return isSet; } cannam@147: cannam@147: private: cannam@147: bool isSet; cannam@147: cannam@147: #if _MSC_VER cannam@147: #pragma warning(push) cannam@147: #pragma warning(disable: 4624) cannam@147: // Warns that the anonymous union has a deleted destructor when T is non-trivial. This warning cannam@147: // seems broken. cannam@147: #endif cannam@147: cannam@147: union { cannam@147: T value; cannam@147: }; cannam@147: cannam@147: #if _MSC_VER cannam@147: #pragma warning(pop) cannam@147: #endif cannam@147: cannam@147: friend class kj::Maybe; cannam@147: template cannam@147: friend NullableValue&& readMaybe(Maybe&& maybe); cannam@147: }; cannam@147: cannam@147: template cannam@147: inline NullableValue&& readMaybe(Maybe&& maybe) { return kj::mv(maybe.ptr); } cannam@147: template cannam@147: inline T* readMaybe(Maybe& maybe) { return maybe.ptr; } cannam@147: template cannam@147: inline const T* readMaybe(const Maybe& maybe) { return maybe.ptr; } cannam@147: template cannam@147: inline T* readMaybe(Maybe&& maybe) { return maybe.ptr; } cannam@147: template cannam@147: inline T* readMaybe(const Maybe& maybe) { return maybe.ptr; } cannam@147: cannam@147: template cannam@147: inline T* readMaybe(T* ptr) { return ptr; } cannam@147: // Allow KJ_IF_MAYBE to work on regular pointers. cannam@147: cannam@147: } // namespace _ (private) cannam@147: cannam@147: #define KJ_IF_MAYBE(name, exp) if (auto name = ::kj::_::readMaybe(exp)) cannam@147: cannam@147: template cannam@147: class Maybe { cannam@147: // A T, or nullptr. cannam@147: cannam@147: // IF YOU CHANGE THIS CLASS: Note that there is a specialization of it in memory.h. cannam@147: cannam@147: public: cannam@147: Maybe(): ptr(nullptr) {} cannam@147: Maybe(T&& t) noexcept(noexcept(T(instance()))): ptr(kj::mv(t)) {} cannam@147: Maybe(T& t): ptr(t) {} cannam@147: Maybe(const T& t): ptr(t) {} cannam@147: Maybe(const T* t) noexcept: ptr(t) {} cannam@147: Maybe(Maybe&& other) noexcept(noexcept(T(instance()))): ptr(kj::mv(other.ptr)) {} cannam@147: Maybe(const Maybe& other): ptr(other.ptr) {} cannam@147: Maybe(Maybe& other): ptr(other.ptr) {} cannam@147: cannam@147: template cannam@147: Maybe(Maybe&& other) noexcept(noexcept(T(instance()))) { cannam@147: KJ_IF_MAYBE(val, kj::mv(other)) { cannam@147: ptr.emplace(kj::mv(*val)); cannam@147: } cannam@147: } cannam@147: template cannam@147: Maybe(const Maybe& other) { cannam@147: KJ_IF_MAYBE(val, other) { cannam@147: ptr.emplace(*val); cannam@147: } cannam@147: } cannam@147: cannam@147: Maybe(decltype(nullptr)) noexcept: ptr(nullptr) {} cannam@147: cannam@147: template cannam@147: inline T& emplace(Params&&... params) { cannam@147: // Replace this Maybe's content with a new value constructed by passing the given parametrs to cannam@147: // T's constructor. This can be used to initialize a Maybe without copying or even moving a T. cannam@147: // Returns a reference to the newly-constructed value. cannam@147: cannam@147: return ptr.emplace(kj::fwd(params)...); cannam@147: } cannam@147: cannam@147: inline Maybe& operator=(Maybe&& other) { ptr = kj::mv(other.ptr); return *this; } cannam@147: inline Maybe& operator=(Maybe& other) { ptr = other.ptr; return *this; } cannam@147: inline Maybe& operator=(const Maybe& other) { ptr = other.ptr; return *this; } cannam@147: cannam@147: inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; } cannam@147: inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; } cannam@147: cannam@147: T& orDefault(T& defaultValue) { cannam@147: if (ptr == nullptr) { cannam@147: return defaultValue; cannam@147: } else { cannam@147: return *ptr; cannam@147: } cannam@147: } cannam@147: const T& orDefault(const T& defaultValue) const { cannam@147: if (ptr == nullptr) { cannam@147: return defaultValue; cannam@147: } else { cannam@147: return *ptr; cannam@147: } cannam@147: } cannam@147: cannam@147: template cannam@147: auto map(Func&& f) & -> Maybe()))> { cannam@147: if (ptr == nullptr) { cannam@147: return nullptr; cannam@147: } else { cannam@147: return f(*ptr); cannam@147: } cannam@147: } cannam@147: cannam@147: template cannam@147: auto map(Func&& f) const & -> Maybe()))> { cannam@147: if (ptr == nullptr) { cannam@147: return nullptr; cannam@147: } else { cannam@147: return f(*ptr); cannam@147: } cannam@147: } cannam@147: cannam@147: template cannam@147: auto map(Func&& f) && -> Maybe()))> { cannam@147: if (ptr == nullptr) { cannam@147: return nullptr; cannam@147: } else { cannam@147: return f(kj::mv(*ptr)); cannam@147: } cannam@147: } cannam@147: cannam@147: template cannam@147: auto map(Func&& f) const && -> Maybe()))> { cannam@147: if (ptr == nullptr) { cannam@147: return nullptr; cannam@147: } else { cannam@147: return f(kj::mv(*ptr)); cannam@147: } cannam@147: } cannam@147: cannam@147: private: cannam@147: _::NullableValue ptr; cannam@147: cannam@147: template cannam@147: friend class Maybe; cannam@147: template cannam@147: friend _::NullableValue&& _::readMaybe(Maybe&& maybe); cannam@147: template cannam@147: friend U* _::readMaybe(Maybe& maybe); cannam@147: template cannam@147: friend const U* _::readMaybe(const Maybe& maybe); cannam@147: }; cannam@147: cannam@147: template cannam@147: class Maybe: public DisallowConstCopyIfNotConst { cannam@147: public: cannam@147: Maybe() noexcept: ptr(nullptr) {} cannam@147: Maybe(T& t) noexcept: ptr(&t) {} cannam@147: Maybe(T* t) noexcept: ptr(t) {} cannam@147: cannam@147: template cannam@147: inline Maybe(Maybe& other) noexcept: ptr(other.ptr) {} cannam@147: template cannam@147: inline Maybe(const Maybe& other) noexcept: ptr(other.ptr) {} cannam@147: inline Maybe(decltype(nullptr)) noexcept: ptr(nullptr) {} cannam@147: cannam@147: inline Maybe& operator=(T& other) noexcept { ptr = &other; return *this; } cannam@147: inline Maybe& operator=(T* other) noexcept { ptr = other; return *this; } cannam@147: template cannam@147: inline Maybe& operator=(Maybe& other) noexcept { ptr = other.ptr; return *this; } cannam@147: template cannam@147: inline Maybe& operator=(const Maybe& other) noexcept { ptr = other.ptr; return *this; } cannam@147: cannam@147: inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; } cannam@147: inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; } cannam@147: cannam@147: T& orDefault(T& defaultValue) { cannam@147: if (ptr == nullptr) { cannam@147: return defaultValue; cannam@147: } else { cannam@147: return *ptr; cannam@147: } cannam@147: } cannam@147: const T& orDefault(const T& defaultValue) const { cannam@147: if (ptr == nullptr) { cannam@147: return defaultValue; cannam@147: } else { cannam@147: return *ptr; cannam@147: } cannam@147: } cannam@147: cannam@147: template cannam@147: auto map(Func&& f) -> Maybe()))> { cannam@147: if (ptr == nullptr) { cannam@147: return nullptr; cannam@147: } else { cannam@147: return f(*ptr); cannam@147: } cannam@147: } cannam@147: cannam@147: private: cannam@147: T* ptr; cannam@147: cannam@147: template cannam@147: friend class Maybe; cannam@147: template cannam@147: friend U* _::readMaybe(Maybe&& maybe); cannam@147: template cannam@147: friend U* _::readMaybe(const Maybe& maybe); cannam@147: }; cannam@147: cannam@147: // ======================================================================================= cannam@147: // ArrayPtr cannam@147: // cannam@147: // So common that we put it in common.h rather than array.h. cannam@147: cannam@147: template cannam@147: class ArrayPtr: public DisallowConstCopyIfNotConst { cannam@147: // A pointer to an array. Includes a size. Like any pointer, it doesn't own the target data, cannam@147: // and passing by value only copies the pointer, not the target. cannam@147: cannam@147: public: cannam@147: inline constexpr ArrayPtr(): ptr(nullptr), size_(0) {} cannam@147: inline constexpr ArrayPtr(decltype(nullptr)): ptr(nullptr), size_(0) {} cannam@147: inline constexpr ArrayPtr(T* ptr, size_t size): ptr(ptr), size_(size) {} cannam@147: inline constexpr ArrayPtr(T* begin, T* end): ptr(begin), size_(end - begin) {} cannam@147: inline KJ_CONSTEXPR() ArrayPtr(::std::initializer_list> init) cannam@147: : ptr(init.begin()), size_(init.size()) {} cannam@147: cannam@147: template cannam@147: inline constexpr ArrayPtr(T (&native)[size]): ptr(native), size_(size) {} cannam@147: // Construct an ArrayPtr from a native C-style array. cannam@147: cannam@147: inline operator ArrayPtr() const { cannam@147: return ArrayPtr(ptr, size_); cannam@147: } cannam@147: inline ArrayPtr asConst() const { cannam@147: return ArrayPtr(ptr, size_); cannam@147: } cannam@147: cannam@147: inline size_t size() const { return size_; } cannam@147: inline const T& operator[](size_t index) const { cannam@147: KJ_IREQUIRE(index < size_, "Out-of-bounds ArrayPtr access."); cannam@147: return ptr[index]; cannam@147: } cannam@147: inline T& operator[](size_t index) { cannam@147: KJ_IREQUIRE(index < size_, "Out-of-bounds ArrayPtr access."); cannam@147: return ptr[index]; cannam@147: } cannam@147: cannam@147: inline T* begin() { return ptr; } cannam@147: inline T* end() { return ptr + size_; } cannam@147: inline T& front() { return *ptr; } cannam@147: inline T& back() { return *(ptr + size_ - 1); } cannam@147: inline const T* begin() const { return ptr; } cannam@147: inline const T* end() const { return ptr + size_; } cannam@147: inline const T& front() const { return *ptr; } cannam@147: inline const T& back() const { return *(ptr + size_ - 1); } cannam@147: cannam@147: inline ArrayPtr slice(size_t start, size_t end) const { cannam@147: KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds ArrayPtr::slice()."); cannam@147: return ArrayPtr(ptr + start, end - start); cannam@147: } cannam@147: inline ArrayPtr slice(size_t start, size_t end) { cannam@147: KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds ArrayPtr::slice()."); cannam@147: return ArrayPtr(ptr + start, end - start); cannam@147: } cannam@147: cannam@147: inline ArrayPtr> asBytes() const { cannam@147: // Reinterpret the array as a byte array. This is explicitly legal under C++ aliasing cannam@147: // rules. cannam@147: return { reinterpret_cast*>(ptr), size_ * sizeof(T) }; cannam@147: } cannam@147: inline ArrayPtr> asChars() const { cannam@147: // Reinterpret the array as a char array. This is explicitly legal under C++ aliasing cannam@147: // rules. cannam@147: return { reinterpret_cast*>(ptr), size_ * sizeof(T) }; cannam@147: } cannam@147: cannam@147: inline bool operator==(decltype(nullptr)) const { return size_ == 0; } cannam@147: inline bool operator!=(decltype(nullptr)) const { return size_ != 0; } cannam@147: cannam@147: inline bool operator==(const ArrayPtr& other) const { cannam@147: if (size_ != other.size_) return false; cannam@147: for (size_t i = 0; i < size_; i++) { cannam@147: if (ptr[i] != other[i]) return false; cannam@147: } cannam@147: return true; cannam@147: } cannam@147: inline bool operator!=(const ArrayPtr& other) const { return !(*this == other); } cannam@147: cannam@147: private: cannam@147: T* ptr; cannam@147: size_t size_; cannam@147: }; cannam@147: cannam@147: template cannam@147: inline constexpr ArrayPtr arrayPtr(T* ptr, size_t size) { cannam@147: // Use this function to construct ArrayPtrs without writing out the type name. cannam@147: return ArrayPtr(ptr, size); cannam@147: } cannam@147: cannam@147: template cannam@147: inline constexpr ArrayPtr arrayPtr(T* begin, T* end) { cannam@147: // Use this function to construct ArrayPtrs without writing out the type name. cannam@147: return ArrayPtr(begin, end); cannam@147: } cannam@147: cannam@147: // ======================================================================================= cannam@147: // Casts cannam@147: cannam@147: template cannam@147: To implicitCast(From&& from) { cannam@147: // `implicitCast(value)` casts `value` to type `T` only if the conversion is implicit. Useful cannam@147: // for e.g. resolving ambiguous overloads without sacrificing type-safety. cannam@147: return kj::fwd(from); cannam@147: } cannam@147: cannam@147: template cannam@147: Maybe dynamicDowncastIfAvailable(From& from) { cannam@147: // If RTTI is disabled, always returns nullptr. Otherwise, works like dynamic_cast. Useful cannam@147: // in situations where dynamic_cast could allow an optimization, but isn't strictly necessary cannam@147: // for correctness. It is highly recommended that you try to arrange all your dynamic_casts cannam@147: // this way, as a dynamic_cast that is necessary for correctness implies a flaw in the interface cannam@147: // design. cannam@147: cannam@147: // Force a compile error if To is not a subtype of From. Cross-casting is rare; if it is needed cannam@147: // we should have a separate cast function like dynamicCrosscastIfAvailable(). cannam@147: if (false) { cannam@147: kj::implicitCast(kj::implicitCast(nullptr)); cannam@147: } cannam@147: cannam@147: #if KJ_NO_RTTI cannam@147: return nullptr; cannam@147: #else cannam@147: return dynamic_cast(&from); cannam@147: #endif cannam@147: } cannam@147: cannam@147: template cannam@147: To& downcast(From& from) { cannam@147: // Down-cast a value to a sub-type, asserting that the cast is valid. In opt mode this is a cannam@147: // static_cast, but in debug mode (when RTTI is enabled) a dynamic_cast will be used to verify cannam@147: // that the value really has the requested type. cannam@147: cannam@147: // Force a compile error if To is not a subtype of From. cannam@147: if (false) { cannam@147: kj::implicitCast(kj::implicitCast(nullptr)); cannam@147: } cannam@147: cannam@147: #if !KJ_NO_RTTI cannam@147: KJ_IREQUIRE(dynamic_cast(&from) != nullptr, "Value cannot be downcast() to requested type."); cannam@147: #endif cannam@147: cannam@147: return static_cast(from); cannam@147: } cannam@147: cannam@147: // ======================================================================================= cannam@147: // Defer cannam@147: cannam@147: namespace _ { // private cannam@147: cannam@147: template cannam@147: class Deferred { cannam@147: public: cannam@147: inline Deferred(Func&& func): func(kj::fwd(func)), canceled(false) {} cannam@147: inline ~Deferred() noexcept(false) { if (!canceled) func(); } cannam@147: KJ_DISALLOW_COPY(Deferred); cannam@147: cannam@147: // This move constructor is usually optimized away by the compiler. cannam@147: inline Deferred(Deferred&& other): func(kj::mv(other.func)), canceled(false) { cannam@147: other.canceled = true; cannam@147: } cannam@147: private: cannam@147: Func func; cannam@147: bool canceled; cannam@147: }; cannam@147: cannam@147: } // namespace _ (private) cannam@147: cannam@147: template cannam@147: _::Deferred defer(Func&& func) { cannam@147: // Returns an object which will invoke the given functor in its destructor. The object is not cannam@147: // copyable but is movable with the semantics you'd expect. Since the return type is private, cannam@147: // you need to assign to an `auto` variable. cannam@147: // cannam@147: // The KJ_DEFER macro provides slightly more convenient syntax for the common case where you cannam@147: // want some code to run at current scope exit. cannam@147: cannam@147: return _::Deferred(kj::fwd(func)); cannam@147: } cannam@147: cannam@147: #define KJ_DEFER(code) auto KJ_UNIQUE_NAME(_kjDefer) = ::kj::defer([&](){code;}) cannam@147: // Run the given code when the function exits, whether by return or exception. cannam@147: cannam@147: } // namespace kj cannam@147: cannam@147: #endif // KJ_COMMON_H_