89 lines
2.7 KiB
C++
89 lines
2.7 KiB
C++
|
//
|
||
|
// 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);
|