Program Listing for File context.hpp

Return to documentation for file (SeQuant/core/utility/context.hpp)

#ifndef SEQUANT_CORE_UTILITY_CONTEXT_HPP
#define SEQUANT_CORE_UTILITY_CONTEXT_HPP

#include <optional>



namespace sequant::detail {

template <typename Ctx>
inline Ctx& implicit_context_instance() {
  static Ctx instance_;
  return instance_;
}

template <typename Ctx>
const Ctx& get_implicit_context() {
  return implicit_context_instance<Ctx>();
}

template <typename Ctx>
void set_implicit_context(const Ctx& ctx) {
  implicit_context_instance<Ctx>() = ctx;
}

template <typename Ctx>
void reset_implicit_context() {
  implicit_context_instance<Ctx>() = Ctx{};
}

template <typename Ctx>
struct ImplicitContextResetter {
  ImplicitContextResetter() = default;
  ImplicitContextResetter(const Ctx& previous_ctx) noexcept
      : previous_ctx_(previous_ctx) {}
  ~ImplicitContextResetter() noexcept {
    if (previous_ctx_) set_implicit_context<Ctx>(*previous_ctx_);
  }

  // ContextResetter is move-only
  ImplicitContextResetter(const ImplicitContextResetter&) = delete;
  ImplicitContextResetter& operator=(const ImplicitContextResetter&) = delete;

 private:
  std::optional<Ctx> previous_ctx_;
};

template <typename Ctx>
ImplicitContextResetter<Ctx> set_scoped_implicit_context(const Ctx& ctx) {
  if (get_implicit_context<Ctx>() != ctx) {
    auto previous_ctx = get_implicit_context<Ctx>();
    set_implicit_context(ctx);
    return previous_ctx;
  } else
    return {};
}

}  // namespace sequant::detail


#endif  // SEQUANT_CORE_UTILITY_CONTEXT_HPP