5#ifndef MOLYBDEN_JS_PROXY_OBJECT_DETAIL_HPP
6#define MOLYBDEN_JS_PROXY_OBJECT_DETAIL_HPP
9#include "molybden/js/js_proxy_object.hpp"
14#include "molybden/base/rtti.hpp"
27struct sfinae_true : std::true_type {};
33template <
class C,
class T>
34class CustomDowncastDefined {
37 static sfinae_true<
decltype(U::downcast(std::shared_ptr<C>{}))> test(
int);
42 static std::false_type test(
long);
48 static constexpr bool isReturnTypeCorrect(std::true_type type) {
49 using bool_type = std::integral_constant<
51 std::is_same<std::shared_ptr<T>,
52 decltype(T::downcast(std::shared_ptr<C>{}))>::value>;
53 static_assert(bool_type::value,
54 "The return value of the downcast method of the class T must "
55 "be of type std::shared_ptr<T>");
56 return bool_type::value;
59 static constexpr bool isReturnTypeCorrect(std::false_type) {
return false; }
65 static constexpr bool value() {
66 using bool_type =
decltype(test<T>(0));
68 return bool_type::value && isReturnTypeCorrect(bool_type());
75 using BoolType = std::integral_constant<bool, value()>;
85template <
class C,
bool rtti = RTTI::Enabled()>
89class ProxyDowncaster<C, true> {
91 static std::shared_ptr<T> downcastImpl(std::shared_ptr<C>
object,
93 return std::dynamic_pointer_cast<T>(std::move(
object));
97 static std::shared_ptr<T> downcastImpl(std::shared_ptr<C>
object,
99 return T::downcast(std::move(
object));
104 static std::shared_ptr<T> downcast(std::shared_ptr<C>
object) {
105 auto return_value = downcastImpl<T>(
107 typename CustomDowncastDefined<C, T>::BoolType());
108 assert(!return_value || return_value ==
object);
112 static std::shared_ptr<C> downcast(std::shared_ptr<C>
object) {
118class ProxyDowncaster<C, false> {
121 static std::shared_ptr<T> downcast(std::shared_ptr<C>
object) {
123 CustomDowncastDefined<C, T>::value(),
124 "RTTI is disabled. Cast from proxy object base class must be\n"
125 "explicitly defined as the static function in the class to downcast "
127 "In terms of C and T:\n"
130 " static std::shared_ptr<T> downcast(std::shared_ptr<T>);\n"
133 return T::downcast(
object);
141class ProxyObjectType {};
144class ProxyObjectTypeImpl :
public ProxyObjectType {
146 static ProxyObjectTypeImpl* instance() {
147 static ProxyObjectTypeImpl impl;
157class JsProxyObjectRoot {
159 static constexpr C* pass(JsProxyObjectImpl<C>*) {
163 static constexpr void* pass(
void*) {
return nullptr; }
167 typename std::remove_pointer<decltype(pass(&std::declval<T&>()))>::type;
168 static constexpr bool Exists = !std::is_same<Type, void>::value;
175 static_assert(internal::JsProxyObjectRoot<T>::Exists,
176 "The object is not a custom proxy object.");
177 using RootProxyType =
typename internal::JsProxyObjectRoot<T>::Type;
178 if (proxyType() == internal::ProxyObjectTypeImpl<RootProxyType>::instance()) {
179 return internal::ProxyDowncaster<RootProxyType>::template downcast<T>(
180 std::static_pointer_cast<RootProxyType>(shared_from_this()));
190 return internal::ProxyObjectTypeImpl<C>::instance();
std::shared_ptr< T > as()
Downcasts the object to the appropriate proxy type.
Definition js_proxy_object_detail.hpp:174
Derive C from JsProxyObjectImpl<C> via CRTP pattern and implement the interface of JsProxyObject.
Definition js_proxy_object.hpp:171