// // 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);