5#ifndef MOLYBDEN_JS_PROXY_OBJECT_DETAIL_HPP
6#define MOLYBDEN_JS_PROXY_OBJECT_DETAIL_HPP
8#include "molybden/js/js_proxy_object.hpp"
13#include "molybden/base/rtti.hpp"
26struct sfinae_true : std::true_type {};
32template <
class C,
class T>
33class CustomDowncastDefined {
36 static sfinae_true<
decltype(U::downcast(std::shared_ptr<C>{}))> test(
int);
41 static std::false_type test(
long);
47 static constexpr bool isReturnTypeCorrect(std::true_type type) {
48 using bool_type = std::integral_constant<
50 std::is_same<std::shared_ptr<T>,
51 decltype(T::downcast(std::shared_ptr<C>{}))>::value>;
52 static_assert(bool_type::value,
53 "The return value of the downcast method of the class T must "
54 "be of type std::shared_ptr<T>");
55 return bool_type::value;
58 static constexpr bool isReturnTypeCorrect(std::false_type) {
return false; }
64 static constexpr bool value() {
65 using bool_type =
decltype(test<T>(0));
67 return bool_type::value && isReturnTypeCorrect(bool_type());
74 using BoolType = std::integral_constant<bool, value()>;
84template <
class C,
bool rtti = RTTI::Enabled()>
88class ProxyDowncaster<C, true> {
90 static std::shared_ptr<T> downcastImpl(std::shared_ptr<C>
object,
92 return std::dynamic_pointer_cast<T>(std::move(
object));
96 static std::shared_ptr<T> downcastImpl(std::shared_ptr<C>
object,
98 return T::downcast(std::move(
object));
103 static std::shared_ptr<T> downcast(std::shared_ptr<C>
object) {
104 auto return_value = downcastImpl<T>(
106 typename CustomDowncastDefined<C, T>::BoolType());
107 assert(!return_value || return_value ==
object);
111 static std::shared_ptr<C> downcast(std::shared_ptr<C>
object) {
117class ProxyDowncaster<C, false> {
120 static std::shared_ptr<T> downcast(std::shared_ptr<C>
object) {
122 CustomDowncastDefined<C, T>::value(),
123 "RTTI is disabled. Cast from proxy object base class must be\n"
124 "explicitly defined as the static function in the class to downcast "
126 "In terms of C and T:\n"
129 " static std::shared_ptr<T> downcast(std::shared_ptr<T>);\n"
132 return T::downcast(
object);
140class ProxyObjectType {};
143class ProxyObjectTypeImpl :
public ProxyObjectType {
145 static ProxyObjectTypeImpl* instance() {
146 static ProxyObjectTypeImpl impl;
156class JsProxyObjectRoot {
158 static constexpr C* pass(JsProxyObjectImpl<C>*) {
162 static constexpr void* pass(
void*) {
return nullptr; }
166 typename std::remove_pointer<decltype(pass(&std::declval<T&>()))>::type;
167 static constexpr bool Exists = !std::is_same<Type, void>::value;
174 static_assert(internal::JsProxyObjectRoot<T>::Exists,
175 "The object is not a custom proxy object.");
176 using RootProxyType =
typename internal::JsProxyObjectRoot<T>::Type;
177 if (proxyType() == internal::ProxyObjectTypeImpl<RootProxyType>::instance()) {
178 return internal::ProxyDowncaster<RootProxyType>::template downcast<T>(
179 std::static_pointer_cast<RootProxyType>(shared_from_this()));
189 return internal::ProxyObjectTypeImpl<C>::instance();
std::shared_ptr< T > as()
Downcasts the object to the appropriate proxy type.
Definition js_proxy_object_detail.hpp:173
Derive C from JsProxyObjectImpl<C> via CRTP pattern and implement the interface of JsProxyObject.
Definition js_proxy_object.hpp:171