FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

// Copyright (c) Herb Sutter // SPDX-License-Identifier: CC-BY-NC-ND-4.0 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. //=========================================================================== // Cpp2 utilities: // Language support implementations // #include'd by generated Cpp1 code //=========================================================================== #ifndef __CPP2_UTIL #define __CPP2_UTIL // If this implementation doesn't support source_location yet, disable it // TODO: technically this test should have included first, but GEFN #if !defined(_MSC_VER) && !defined(__cpp_lib_source_location) #undef CPP2_USE_SOURCE_LOCATION #endif // If the cppfront user requested -pure-cpp2, this will be set // and we should be using modules only #ifdef CPP2_USE_MODULES // If we have real modules, use those the best we can // as implementations are still underway #ifdef __cpp_modules #ifndef _MSC_VER // This is the ideal -- note that we just voted "import std;" // into draft C++23 in late July 2022, so implementers haven't // had time to catch up yet. As of this writing (September 2022) // no compiler will take this path yet, but they're on the way... import std; #else // MSVC // Note: When C++23 "import std;" is available, we will switch to that here // In the meantime, this is what works on MSVC which is the only compiler // I've been able to get access to that implements modules enough to demo // (but we'll have more full-C++20 compilers soon!) import std.core; import std.regex; import std.filesystem; import std.memory; import std.threading; // Suppress spurious MSVC modules warning #pragma warning(disable:5050) #endif // Otherwise, "fake it till you make it"... include (nearly) all the // standard headers, with a feature test #ifdef for each header that // isn't yet supported by all of { VS 2022, g++-10, clang++-12 } // ... this should approximate "import std;" on those compilers #else #include #include #ifdef __cpp_lib_coroutine #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __cpp_lib_source_location #include #endif #include #include #include #include #include #include #include #ifdef __cpp_lib_memory_resource #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if __has_include() #include #endif #include #include #ifdef __cpp_lib_format #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __cpp_lib_spanstream #include #endif #include #include #ifdef __cpp_lib_syncstream #include #endif #include #include #include #ifdef __cpp_lib_barrier #include #endif #include #include #ifdef __cpp_lib_latch #include #endif #include #ifdef __cpp_lib_semaphore #include #endif #include #ifdef __cpp_lib_jthread #include #endif #include #include // libstdc++ currently has a dependency on linking TBB if is // included, and TBB seems to be not automatically installed and linkable // on some GCC installations, so let's not pull in that little-used header // in our -pure-cpp2 "import std;" simulation mode... if you need this, // use mixed mode (not -pure-cpp2) and #include all the headers you need // including this one // // #include #endif // Otherwise, we're not in -pure-cpp2 and so just #include // what we need in this header to make this self-contained #else #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(CPP2_USE_SOURCE_LOCATION) #include #endif #endif #define CPP2_TYPEOF(x) std::remove_cvref_t #define CPP2_FORWARD(x) std::forward(x) namespace cpp2 { //----------------------------------------------------------------------- // // Convenience names for fundamental types // // Note: De jure, some of these are optional per the C and C++ standards // De facto, all of these are supported in all implementations I know of // //----------------------------------------------------------------------- // // Encouraged by default: Fixed-precision names using i8 = std::int8_t ; using i16 = std::int16_t ; using i32 = std::int32_t ; using i64 = std::int64_t ; using u8 = std::uint8_t ; using u16 = std::uint16_t ; using u32 = std::uint32_t ; using u64 = std::uint64_t ; // Rarely, when really needed for speed optimization: Fastest type with at least N bits using i8_fast = std::int_fast8_t ; using i16_fast = std::int_fast16_t ; using i32_fast = std::int_fast32_t ; using i64_fast = std::int_fast64_t ; using u8_fast = std::uint_fast8_t ; using u16_fast = std::uint_fast16_t ; using u32_fast = std::uint_fast32_t ; using u64_fast = std::uint_fast64_t ; // Rarely, when really needed for space optimization: Smallest type with at least N bits using i8_small = std::int_least8_t ; using i16_small = std::int_least16_t ; using i32_small = std::int_least32_t ; using i64_small = std::int_least64_t ; using u8_small = std::uint_least8_t ; using u16_small = std::uint_least16_t; using u32_small = std::uint_least32_t; using u64_small = std::uint_least64_t; // Discouraged: Variable precision names // short using ushort = unsigned short; // int using ulong = unsigned long; // long using longlong = long long; using ulonglong = unsigned long long; using longdouble = long double; // Strongly discouraged, for compatibility/interop only using __schar = signed char; // normally use i8 instead using __uchar = unsigned char; // normally use u8 instead //----------------------------------------------------------------------- // // contract_group // //----------------------------------------------------------------------- // #ifdef CPP2_USE_SOURCE_LOCATION #define CPP2_SOURCE_LOCATION_PARAM , std::source_location where #define CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT , std::source_location where = std::source_location::current() #define CPP2_SOURCE_LOCATION_PARAM_SOLO std::source_location where #define CPP2_SOURCE_LOCATION_ARG , where #else #define CPP2_SOURCE_LOCATION_PARAM #define CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT #define CPP2_SOURCE_LOCATION_PARAM_SOLO #define CPP2_SOURCE_LOCATION_ARG #endif // For C++23: make this std::string_view and drop the macro // Before C++23 std::string_view was not guaranteed to be trivially copyable, // and so in will pass it by const& and really it should be by value #define CPP2_MESSAGE_PARAM char const* class contract_group { public: using handler = void (*)(CPP2_MESSAGE_PARAM msg CPP2_SOURCE_LOCATION_PARAM); constexpr contract_group (handler h = {}) : reporter(h) { } constexpr auto set_handler(handler h) -> handler; constexpr auto get_handler() const -> handler { return reporter; } constexpr auto expects (bool b, CPP2_MESSAGE_PARAM msg = "" CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT) -> void { if (!b) reporter(msg CPP2_SOURCE_LOCATION_ARG); } private: handler reporter; }; [[noreturn]] inline auto report_and_terminate(std::string_view group, CPP2_MESSAGE_PARAM msg = "" CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT) noexcept -> void { std::cerr #ifdef CPP2_USE_SOURCE_LOCATION std::string { return "(customize me - no cpp2::to_string overload exists for this type)"; } inline auto to_string(std::any const&) -> std::string { return "std::any"; } template inline auto to_string(T const& t) -> std::string requires requires { std::to_string(t); } { return std::to_string(t); } inline auto to_string(char const* s) -> std::string { return std::string{s}; } inline auto to_string(std::string const& s) -> std::string const& { return s; } template inline auto to_string(T const& sv) -> std::string requires (std::is_convertible_v && !std::is_convertible_v) { return std::string{sv}; } template inline auto to_string(std::variant const& v) -> std::string; template < typename T, typename U> inline auto to_string(std::pair const& p) -> std::string; template < typename... Ts> inline auto to_string(std::tuple const& t) -> std::string; template inline auto to_string(std::optional const& o) -> std::string { if (o.has_value()) { return cpp2::to_string(o.value()); } return "(empty)"; } template inline auto to_string(std::variant const& v) -> std::string { if (v.valueless_by_exception()) return "(empty)"; // Need to guard this with is_any otherwise the get_if is illegal if constexpr (is_any) if (std::get_if(&v) != nullptr) return "(empty)"; return std::visit([](auto&& arg) -> std::string { return cpp2::to_string(arg); }, v); } template < typename T, typename U> inline auto to_string(std::pair const& p) -> std::string { return "(" + cpp2::to_string(p.first) + ", " + cpp2::to_string(p.second) + ")"; } template < typename... Ts> inline auto to_string(std::tuple const& t) -> std::string { if constexpr (sizeof...(Ts) == 0) { return "()"; } else { std::string out = "(" + cpp2::to_string(std::get(t)); std::apply([&out](auto&&, auto&&... args) { ((out += ", " + cpp2::to_string(args)), ...); }, t); out += ")"; return out; } } //----------------------------------------------------------------------- // // Speculative: RAII wrapping for the C standard library // // As part of embracing compatibility while also reducing what we have to // teach and learn about C++ (which includes the C standard library), I // was curious to see if we can improve use of the C standard library // from Cpp2 code... UFCS is a part of that, and then RAII destructors is // another that goes hand in hand with that, hence this section... // but see caveat note at the end. // //----------------------------------------------------------------------- // template class c_raii { T t; D dtor; public: c_raii( T t_, D d ) : t{ t_ } , dtor{ d } { } ~c_raii() { dtor(t); } operator T&() { return t; } c_raii(c_raii const&) = delete; auto operator=(c_raii const&) = delete; }; inline auto fopen( const char* filename, const char* mode ) { // Suppress annoying deprecation warning about fopen #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable : 4996 ) #endif auto x = std::fopen(filename, mode); #ifdef _MSC_VER #pragma warning( pop ) #endif if (!x) { throw std::make_error_condition(std::errc::no_such_file_or_directory); } return c_raii( x, &fclose ); } // Caveat: There's little else in the C stdlib that allocates a resource... // // malloc is already wrapped like this via std::unique_ptr, which // typically uses malloc or gets memory from the same pool // thrd_create std::jthread is better // // ... is that it? I don't think it's useful to provide a c_raii just for fopen, // but perhaps c_raii may be useful for bringing forward third-party C code too, // with cpp2::fopen as a starting example. } using cpp2::cpp2_new; //----------------------------------------------------------------------- // // A partial implementation of GSL features Cpp2 relies on, // to keep this a standalone header without non-std dependencies // //----------------------------------------------------------------------- // namespace gsl { //----------------------------------------------------------------------- // // An implementation of GSL's narrow_cast // //----------------------------------------------------------------------- // template constexpr auto narrow_cast(From&& from) noexcept -> To { return static_cast(std::forward(from)); } } #endif

Back | FazBrowse Home | New Git URL