// // 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 namespace scm { namespace detail { template 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 , val>{} && !std::is_same, SCM>{})>> val(T&& x) : base_t(detail::to_scm(std::forward(x))) {} template (SCM{}))>{}>> operator T() const { return detail::to_cpp(handle_); } template (SCM{}))>{}>> operator T& () const { return detail::to_cpp(handle_); } template (SCM{}))>{}>> operator const T& () const { return detail::to_cpp(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 \ : convert_wrapper_type {}; \ }} /* namespace scm::detail */ \ /**/ SCM_DECLARE_WRAPPER_TYPE(val);