diff options
Diffstat (limited to 'extra/guile/scm/val.hpp')
-rw-r--r-- | extra/guile/scm/val.hpp | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/extra/guile/scm/val.hpp b/extra/guile/scm/val.hpp new file mode 100644 index 000000000000..63d7189262da --- /dev/null +++ b/extra/guile/scm/val.hpp @@ -0,0 +1,88 @@ +// +// immer: immutable data structures for C++ +// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente +// +// This software is distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt +// + +#pragma once + +#include <scm/detail/convert.hpp> + +namespace scm { +namespace detail { + +template <typename T> +struct convert_wrapper_type +{ + static T to_cpp(SCM v) { return T{v}; } + static SCM to_scm(T v) { return v.get(); } +}; + +struct wrapper +{ + wrapper() = default; + wrapper(SCM hdl) : handle_{hdl} {} + SCM get() const { return handle_; } + operator SCM () const { return handle_; } + + bool operator==(wrapper other) { return handle_ == other.handle_; } + bool operator!=(wrapper other) { return handle_ != other.handle_; } + +protected: + SCM handle_ = SCM_UNSPECIFIED; +}; + +} // namespace detail + +struct val : detail::wrapper +{ + using base_t = detail::wrapper; + using base_t::base_t; + + template <typename T, + typename = std::enable_if_t< + (!std::is_same<std::decay_t<T>, val>{} && + !std::is_same<std::decay_t<T>, SCM>{})>> + val(T&& x) + : base_t(detail::to_scm(std::forward<T>(x))) + {} + + template <typename T, + typename = std::enable_if_t< + std::is_same<T, decltype(detail::to_cpp<T>(SCM{}))>{}>> + operator T() const { return detail::to_cpp<T>(handle_); } + + template <typename T, + typename = std::enable_if_t< + std::is_same<T&, decltype(detail::to_cpp<T>(SCM{}))>{}>> + operator T& () const { return detail::to_cpp<T>(handle_); } + + template <typename T, + typename = std::enable_if_t< + std::is_same<const T&, decltype(detail::to_cpp<T>(SCM{}))>{}>> + operator const T& () const { return detail::to_cpp<T>(handle_); } + + val operator() () const + { return val{scm_call_0(get())}; } + val operator() (val a0) const + { return val{scm_call_1(get(), a0)}; } + val operator() (val a0, val a1) const + { return val{scm_call_2(get(), a0, a1)}; } + val operator() (val a0, val a1, val a3) const + { return val{scm_call_3(get(), a0, a1, a3)}; } +}; + +} // namespace scm + +#define SCM_DECLARE_WRAPPER_TYPE(cpp_name__) \ + namespace scm { \ + namespace detail { \ + template <> \ + struct convert<cpp_name__> \ + : convert_wrapper_type<cpp_name__> {}; \ + }} /* namespace scm::detail */ \ + /**/ + +SCM_DECLARE_WRAPPER_TYPE(val); |