// file : build/utility -*- C++ -*- // copyright : Copyright (c) 2014-2015 Code Synthesis Ltd // license : MIT; see accompanying LICENSE file #ifndef BUILD_UTILITY #define BUILD_UTILITY #include <tuple> #include <string> #include <utility> #include <exception> #include <unordered_set> #include <build/types> namespace build { // Empty string and path. // extern const std::string empty_string; extern const path empty_path; extern const dir_path empty_dir_path; // Call a function if there is an exception. // // Means we are in the body of a destructor that is being called // as part of the exception stack unwindining. Used to compensate // for the deficiencies of uncaught_exception() until C++17 // uncaught_exceptions() becomes available. // // @@ MT: will have to be TLS. // extern bool exception_unwinding_dtor; template <typename F, typename T> struct exception_guard; template <typename F, typename... A> inline exception_guard<F, std::tuple<A&&...>> make_exception_guard (F f, A&&... a) { return exception_guard<F, std::tuple<A&&...>> ( std::move (f), std::forward_as_tuple (a...)); } template <typename F, typename... A> struct exception_guard<F, std::tuple<A...>> { typedef std::tuple<A...> T; exception_guard (F f, T a): f_ (std::move (f)), a_ (std::move (a)) {} ~exception_guard () { if (std::uncaught_exception ()) { exception_unwinding_dtor = true; call (std::index_sequence_for<A...> ()); exception_unwinding_dtor = false; } } private: template <std::size_t... I> void call (std::index_sequence<I...>) {f_ (std::get<I> (a_)...);} F f_; T a_; }; // Pools (@@ perhaps move into a separate header). // struct string_pool: std::unordered_set<std::string> { const std::string& find (const char* s) {return *emplace (s).first;} const std::string& find (const std::string& s) {return *emplace (s).first;} }; extern string_pool extension_pool; } #endif // BUILD_UTILITY