diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7f2836a6..77dd586b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.10)
 
-project(msft_proxy VERSION 3.2.1 LANGUAGES CXX)
+project(msft_proxy VERSION 3.3.0 LANGUAGES CXX)
 add_library(msft_proxy INTERFACE)
 target_compile_features(msft_proxy INTERFACE cxx_std_20)
 target_include_directories(msft_proxy INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
diff --git a/README.md b/README.md
index e3f89242..80fb1052 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ Please refer to the [Proxy's Frequently Asked Questions](https://microsoft.githu
 
 ### Hello World
 
-Let's get started with the following "Hello World" example:
+Let's get started with the following "Hello World" example ([run](https://godbolt.org/z/jr81Poz83)):
 
 ```cpp
 #include <format>
@@ -80,7 +80,7 @@ Here is a step-by-step explanation:
 
 ### Hello World (Stream Version)
 
-In the previous "Hello Word" example, we demonstrated how `proxy` could manage different types of objects and be formatted with `std::format`. While `std::format` is not the only option to print objects in C++, can we simply make `proxy` work with `std::cout`? The answer is "yes". The previous example is equivalent to the following implementation:
+In the previous "Hello Word" example, we demonstrated how `proxy` could manage different types of objects and be formatted with `std::format`. While `std::format` is not the only option to print objects in C++, can we simply make `proxy` work with `std::cout`? The answer is "yes". The previous example is equivalent to the following implementation ([run](https://godbolt.org/z/q1b14WGff)):
 
 ```cpp
 #include <iomanip>
@@ -136,7 +136,7 @@ In addition to the operator expressions demonstrated in the previous examples, t
 - [class template `pro::operator_dispatch`](https://microsoft.github.io/proxy/docs/operator_dispatch.html): Dispatch type for operator expressions.
 - [class `explicit_conversion_dispatch` (aka. `conversion_dispatch`)](https://microsoft.github.io/proxy/docs/explicit_conversion_dispatch.html) and [class `implicit_conversion_dispatch`](https://microsoft.github.io/proxy/docs/implicit_conversion_dispatch.html): Dispatch type for conversion expressions.
 
-Note that some facilities are provided as macro, because C++ templates today do not support generating a function with an arbitrary name. Here is another example that makes member function call expressions polymorphic:
+Note that some facilities are provided as macro, because C++ templates today do not support generating a function with an arbitrary name. Here is another example that makes member function call expressions polymorphic ([run](https://godbolt.org/z/xcEeYrjnY)):
 
 ```cpp
 #include <iostream>
@@ -205,11 +205,13 @@ The "Proxy" library is a self-contained solution for runtime polymorphism in C++
 
 - **Overloading**: [`facade_builder::add_convention`](https://microsoft.github.io/proxy/docs/basic_facade_builder/add_convention.html) is more powerful than demonstrated above. It can take any number of overload types (formally, any type meeting the [*ProOverload* requirements](https://microsoft.github.io/proxy/docs/ProOverload.html)) and perform standard overload resolution when invoking a `proxy`.
 - **Facade composition**: [`facade_builder::add_facade`](https://microsoft.github.io/proxy/docs/basic_facade_builder/add_facade.html) allows flexible composition of different abstractions.
+- **Concepts**: To facilitate template programming with "Proxy", 3 concepts are exported from a facade type. Namely, [`proxiable`](https://microsoft.github.io/proxy/docs/proxiable.html), [`proxiable_target`](https://microsoft.github.io/proxy/docs/proxiable_target.html) and [`inplace_proxiable_target`](https://microsoft.github.io/proxy/docs/inplace_proxiable_target.html).
 - **Allocator awareness**: [function template `allocate_proxy`](https://microsoft.github.io/proxy/docs/allocate_proxy.html) is able to create a `proxy` from a value with any custom allocator. In C++11, [`std::function`](https://en.cppreference.com/w/cpp/utility/functional/function) and [`std::packaged_task`](https://en.cppreference.com/w/cpp/thread/packaged_task) had constructors that accepted custom allocators for performance tuning, but these were [removed in C++17](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0302r1.html) because "the semantics are unclear, and there are technical issues with storing an allocator in a type-erased context and then recovering that allocator later for any allocations needed during copy assignment". These issues do not apply to `allocate_proxy`.
 - **Configurable constraints**: [`facade_builder`](https://microsoft.github.io/proxy/docs/basic_facade_builder.html) provides full support for constraints configuration, including memory layout (by [`restrict_layout`](https://microsoft.github.io/proxy/docs/basic_facade_builder/restrict_layout.html)), copyability (by [`support_copy`](https://microsoft.github.io/proxy/docs/basic_facade_builder/support_copy.html)), relocatability (by [`support_relocation`](https://microsoft.github.io/proxy/docs/basic_facade_builder/support_relocation.html)), and destructibility (by [`support_destruction`](https://microsoft.github.io/proxy/docs/basic_facade_builder/support_destruction.html)).
 - **Reflection**: `proxy` supports type-based compile-time reflection for runtime queries. Please refer to [`facade_builder::add_reflection`](https://microsoft.github.io/proxy/docs/basic_facade_builder/add_reflection.html) and [function template `proxy_reflect`](https://microsoft.github.io/proxy/docs/proxy_reflect.html) for more details.
-- **Non-owning proxy**: Although `proxy` can manage the lifetime of an object effectively, similar to a smart pointer, we sometimes want to dereference it before passing to a non-owning context. This has been implemented as an extension since 3.2. Please refer to [alias template `proxy_view`, class template `observer_facade`](https://microsoft.github.io/proxy/docs/proxy_view.html) and [`facade_builder::support_view`](https://microsoft.github.io/proxy/docs/basic_facade_builder/support_view.html) for more details.
+- **Non-owning proxy**: Although `proxy` can manage the lifetime of an object effectively, similar to a smart pointer, we sometimes want to dereference it before passing to a non-owning context. This has been implemented as an extension since 3.2.0. Please refer to [function template `make_proxy_view`](https://microsoft.github.io/proxy/docs/make_proxy_view.html), [alias template `proxy_view`, class template `observer_facade`](https://microsoft.github.io/proxy/docs/proxy_view.html) and [`facade_builder::support_view`](https://microsoft.github.io/proxy/docs/basic_facade_builder/support_view.html) for more details.
 - **RTTI**: [RTTI (run-time type information)](https://en.wikipedia.org/wiki/Run-time_type_information) provides "weak" reflection capability in C++ since the last century. Although it is not as powerful as reflection in some other languages (like `Object.GetType()` in C# or `Object.getClass()` in Java), it offers the basic infrastructure for type-safe casting at runtime. Since 3.2, "RTTI for `proxy`" has been implemented as an extension and allows users to opt-in for each facade definition. Please refer to [`facade_builder::support_rtti`](https://microsoft.github.io/proxy/docs/basic_facade_builder/support_rtti.html) for more details.
+- **Shared and weak ownership**: Although `proxy` can be created from a [`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr), extensions are available to create `proxy` objects with shared and weak ownership in a more efficient way since 3.3.0. Please refer to [function template `make_proxy_shared`](https://microsoft.github.io/proxy/docs/make_proxy_shared.html), [`allocate_proxy_shared`](https://microsoft.github.io/proxy/docs/allocate_proxy_shared.html), [alias template `weak_proxy`, class template `weak_facade`](https://microsoft.github.io/proxy/docs/weak_proxy.html) and [`facade_builder::support_weak`](https://microsoft.github.io/proxy/docs/basic_facade_builder/support_weak.html) for more details.
 - **Weak dispatch**: When an object does not implement a convention, and we do not want it to trigger a hard compile error, it is allowed to specify a [`weak_dispatch`](https://microsoft.github.io/proxy/docs/weak_dispatch.html) that throws when invoked.
 
 ## <a name="compiler-req">Minimum Requirements for Compilers</a>
diff --git a/docs/PRO_DEF_FREE_AS_MEM_DISPATCH.md b/docs/PRO_DEF_FREE_AS_MEM_DISPATCH.md
index 25b138fc..d2fb494f 100644
--- a/docs/PRO_DEF_FREE_AS_MEM_DISPATCH.md
+++ b/docs/PRO_DEF_FREE_AS_MEM_DISPATCH.md
@@ -27,19 +27,19 @@ struct dispatch_name {
     return func_name(std::forward<T>(self), std::forward<Args>(args)...);
   }
 
-  template <class F, class C, class... Os>
+  template <class F, bool IsDirect, class D, class... Os>
   struct accessor {
     accessor() = delete;
   };
-  template <class F, class C, class... Os>
-      requires(sizeof...(Os) > 1u && (std::is_constructible_v<accessor<F, C, Os>> && ...))
-  struct accessor<F, C, Os...> : accessor<F, C, Os>... {
-    using accessor<F, C, Os>::accessibility_func_name ...;
+  template <class F, bool IsDirect, class D, class... Os>
+      requires(sizeof...(Os) > 1u && (std::is_constructible_v<accessor<F, IsDirect, D, Os>> && ...))
+  struct accessor<F, IsDirect, D, Os...> : accessor<F, IsDirect, D, Os>... {
+    using accessor<F, IsDirect, D, Os>::accessibility_func_name ...;
   };
-  template <class F, class C, class R, class... Args>
-  struct accessor<F, C, R(Args...) cv ref noex> {
+  template <class F, bool IsDirect, class D, class R, class... Args>
+  struct accessor<F, IsDirect, D, R(Args...) cv ref noex> {
     R accessibility_func_name(Args... args) cv ref noex {
-      return pro::proxy_invoke<C, R(Args...) cv ref noex>(pro::access_proxy<F>(std::forward<accessor cv ref>(*this)), std::forward<Args>(args)...);
+      return pro::proxy_invoke<IsDirect, D, R(Args...) cv ref noex>(pro::access_proxy<F>(std::forward<accessor cv ref>(*this)), std::forward<Args>(args)...);
     }
   };
 }
diff --git a/docs/ProReflection.md b/docs/ProReflection.md
index dc75fb5f..02c246ea 100644
--- a/docs/ProReflection.md
+++ b/docs/ProReflection.md
@@ -8,4 +8,4 @@ A type `R` meets the *ProReflection* requirements of a type `P` if `R` meets the
 
 ## See Also
 
-[*ProFacade* requirements](ProFacade.md)
+- [*ProFacade* requirements](ProFacade.md)
diff --git a/docs/access_proxy.md b/docs/access_proxy.md
index 97acc66d..0d1bfe6d 100644
--- a/docs/access_proxy.md
+++ b/docs/access_proxy.md
@@ -1,20 +1,20 @@
 # Function template `access_proxy`
 
 ```cpp
-template <class F, class A>
+template <facade F, class A>
 proxy<F>& access_proxy(A& a) noexcept;
 
-template <class F, class A>
+template <facade F, class A>
 const proxy<F>& access_proxy(const A& a) noexcept;
 
-template <class F, class A>
+template <facade F, class A>
 proxy<F>&& access_proxy(A&& a) noexcept;
 
-template <class F, class A>
+template <facade F, class A>
 const proxy<F>&& access_proxy(const A&& a) noexcept;
 ```
 
-Accesses a `proxy` object from an [accessor](ProAccessible.md) instantiated from the `proxy`. `F` shall model concept [`facade`](facade.md). As per `facade<F>`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing distinct types `Cs`. There shall be a type `C` in `Cs` where `A` is the same type as `typename C::template accessor<F>`. The behavior is undefined if `a` is not instantiated from a `proxy`.
+Accesses a `proxy` object from an [accessor](ProAccessible.md) instantiated from the `proxy`. As per `facade<F>`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing distinct types `Cs`. There shall be a type `C` in `Cs` where `A` is the same type as `typename C::template accessor<F>`. The behavior is undefined if `a` is not instantiated from a `proxy`.
 
 ## Return Value
 
diff --git a/docs/allocate_proxy.md b/docs/allocate_proxy.md
index b4c746f2..cb9a911d 100644
--- a/docs/allocate_proxy.md
+++ b/docs/allocate_proxy.md
@@ -22,6 +22,8 @@ proxy<F> allocate_proxy(const Alloc& alloc, T&& value);  // freestanding-deleted
 
 `(3)` Creates a `proxy<F>` object containing a value `p` of type `allocated-ptr<std::decay_t<T>, Alloc>`, where `*p` is direct-non-list-initialized with `std::forward<T>(value)`.
 
+*Since 3.3.0*: For `(1-3)`, if [`proxiable_target<std::decay_t<T>, F>`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated.
+
 ## Return Value
 
 The constructed `proxy` object.
diff --git a/docs/allocate_proxy_shared.md b/docs/allocate_proxy_shared.md
new file mode 100644
index 00000000..14d6006f
--- /dev/null
+++ b/docs/allocate_proxy_shared.md
@@ -0,0 +1,65 @@
+# Function template `allocate_proxy_shared`
+
+The definition of `allocate_proxy_shared` makes use of exposition-only class templates *strong-compact-ptr* and *weak-compact-ptr*. Their semantics are similar to [`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr) and [`std::weak_ptr`](https://en.cppreference.com/w/cpp/memory/weak_ptr), but do not provide a polymorphic deleter. Their size and alignment are guaranteed not to be greater than those of a raw pointer type. `strong-compact-ptr<T, Alloc>` is conditionally convertible to `weak-compact-ptr<T, Alloc>` only if necessary. Similar to [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional), `strong-compact-ptr<T, Alloc>` provides `operator*` for accessing the managed object of type `T` with the same qualifiers.
+
+```cpp
+// (1)
+template <facade F, class T, class Alloc, class... Args>
+proxy<F> allocate_proxy_shared(const Alloc& alloc, Args&&... args);  // freestanding-deleted
+
+// (2)
+template <facade F, class T, class Alloc, class U, class... Args>
+proxy<F> allocate_proxy_shared(const Alloc& alloc, std::initializer_list<U> il, Args&&... args);  // freestanding-deleted
+
+// (3)
+template <facade F, class Alloc, class T>
+proxy<F> allocate_proxy_shared(const Alloc& alloc, T&& value);  // freestanding-deleted
+```
+
+`(1)` Creates a `proxy<F>` object containing a value `p` of type `strong-compact-ptr<T, Alloc>`, where `*p` is direct-non-list-initialized with `std::forward<Args>(args)...`.
+
+`(2)` Creates a `proxy<F>` object containing a value `p` of type `strong-compact-ptr<T, Alloc>`, where `*p` is direct-non-list-initialized with `il, std::forward<Args>(args)...`.
+
+`(3)` Creates a `proxy<F>` object containing a value `p` of type `strong-compact-ptr<std::decay_t<T>, Alloc>`, where `*p` is direct-non-list-initialized with `std::forward<T>(value)`.
+
+For `(1-3)`, if [`proxiable_target<std::decay_t<T>, F>`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated.
+
+## Return Value
+
+The constructed `proxy` object.
+
+## Exceptions
+
+Throws any exception thrown by allocation or the constructor of `T`.
+
+## Notes
+
+The implementation of `strong-compact-ptr` may vary depending on the definition of `F`. Specifically, when `F` does not support weak ownership via [`basic_facade_builder::support_weak`](basic_facade_builder/support_weak.md), `strong-compact-ptr<T, Alloc>` is not convertible to `weak-compact-ptr<T, Alloc>`, which leaves more room for optimization.
+
+## Example
+
+```cpp
+#include <iostream>
+#include <memory_resource>
+
+#include "proxy.h"
+
+struct RttiAware : pro::facade_builder
+    ::support_copy<pro::constraint_level::nothrow>
+    ::support_rtti
+    ::build {};
+
+int main() {
+  std::pmr::unsynchronized_pool_resource pool;
+  std::pmr::polymorphic_allocator<> alloc{&pool};
+  pro::proxy<RttiAware> p1 = pro::allocate_proxy_shared<RttiAware>(alloc, 1);
+  pro::proxy<RttiAware> p2 = p1;
+  proxy_cast<int&>(*p1) += 2;
+  std::cout << proxy_cast<int>(*p2) << "\n";  // Prints "3"
+}
+```
+
+## See Also
+
+- [function template `allocate_proxy`](allocate_proxy.md)
+- [named requirements *Allocator*](https://en.cppreference.com/w/cpp/named_req/Allocator)
\ No newline at end of file
diff --git a/docs/basic_facade_builder.md b/docs/basic_facade_builder.md
index 0db2f228..39e5107b 100644
--- a/docs/basic_facade_builder.md
+++ b/docs/basic_facade_builder.md
@@ -33,6 +33,7 @@ using facade_builder = basic_facade_builder<std::tuple<>, std::tuple<>,
 | [`support_format`<br />`support_wformat`](basic_facade_builder/support_format.md)<br />*(since 3.2.0)* | Specifies the capability of formatting (via [formatting functions](https://en.cppreference.com/w/cpp/utility/format)) to the template parameters |
 | [`support_rtti`<br />`support_indirect_rtti`<br />`support_direct_rtti`](basic_facade_builder/support_rtti.md)<br />*(since 3.2.0)* | Specifies the capability of RTTI (via `proxy_cast` and `proxy_typeid`) to the template parameters |
 | [`support_view` ](basic_facade_builder/support_view.md)<br />*(since 3.2.1)* | Specifies the capability of implicit conversion to `proxy_view` to the template parameters |
+| [`support_weak`](basic_facade_builder/support_weak.md)<br />*(since 3.3.0)* | Specifies the capability of implicit conversion to `weak_proxy` to the template parameters |
 
 ## Member Alias Templates
 
diff --git a/docs/basic_facade_builder/support_weak.md b/docs/basic_facade_builder/support_weak.md
new file mode 100644
index 00000000..81a3378c
--- /dev/null
+++ b/docs/basic_facade_builder/support_weak.md
@@ -0,0 +1,43 @@
+# `basic_facade_builder::support_weak`
+
+```cpp
+using support_weak = basic_facade_builder</* see below */>;
+```
+
+The member type `support_weak` of `basic_facade_builder<Cs, Rs, C>` adds necessary convention types to allow implicit conversion from [`proxy`](../proxy.md)`<F>` to [`weak_proxy`](../weak_proxy.md)`<F>` where `F` is a [facade](../facade.md) type built from `basic_facade_builder`.
+
+Let `p` be a value of type `proxy<F>`, `ptr` of type `P` be the contained value of `p` (if any), the conversion from type `const proxy<F>&` to type `weak_proxy<F>` is equivalent to `return typename P::weak_type{ptr}` if `p` contains a value, or otherwise equivalent to `return nullptr`.
+
+## Notes
+
+`support_weak` is compatible with [`std::weak_ptr`](https://en.cppreference.com/w/cpp/memory/weak_ptr), and may generate more efficient code when working with [`make_proxy_shared`](../make_proxy_shared.md) or [`allocate_proxy_shared`](../allocate_proxy_shared.md). It is also compatible with any custom shared/weak ownership implementations if `typename P::weak_type{ptr}` is well-formed.
+
+## Example
+
+```cpp
+#include <iostream>
+
+#include "proxy.h"
+
+struct Formattable : pro::facade_builder
+    ::support_format
+    ::support_weak
+    ::build {};
+
+int main() {
+  pro::proxy<Formattable> p1 = pro::make_proxy_shared<Formattable>(123);
+  pro::weak_proxy<Formattable> wp = p1;
+  pro::proxy<Formattable> p2 = wp.lock();
+  std::cout << std::boolalpha << p2.has_value() << "\n";  // Prints "true"
+  std::cout << std::format("{}\n", *p2);  // Prints "123"
+
+  p1.reset();
+  p2.reset();
+  p2 = wp.lock();
+  std::cout << p2.has_value() << "\n";  // Prints "false"
+}
+```
+
+## See Also
+
+- [`add_convention`](add_convention.md)
diff --git a/docs/facade_aware_overload_t.md b/docs/facade_aware_overload_t.md
index 28d4ad1c..67865984 100644
--- a/docs/facade_aware_overload_t.md
+++ b/docs/facade_aware_overload_t.md
@@ -21,7 +21,7 @@ Class template `facade_aware_overload_t<O>` specifies a facade-aware overload te
 template <class F>
 using BinaryOverload = pro::proxy<F>(const pro::proxy_indirect_accessor<F>& rhs) const;
 
-template <class T, class F>
+template <class T, pro::facade F>
 pro::proxy<F> operator+(const T& value, const pro::proxy_indirect_accessor<F>& rhs)
     requires(!std::is_same_v<T, pro::proxy_indirect_accessor<F>>)
     { return pro::make_proxy<F, T>(value + proxy_cast<const T&>(rhs)); }
diff --git a/docs/formatter_proxy_indirect_accessor.md b/docs/formatter_proxy_indirect_accessor.md
index e2039f5d..1711f4a6 100644
--- a/docs/formatter_proxy_indirect_accessor.md
+++ b/docs/formatter_proxy_indirect_accessor.md
@@ -2,7 +2,7 @@
 
 ```cpp
 namespace std {
-  template <class F, class CharT> requires(/* see below */)
+  template <facade F, class CharT> requires(/* see below */)
   struct formatter<pro::proxy_indirect_accessor<F>, ChatT>;  // since 3.2.0
 }
 ```
diff --git a/docs/implicit_conversion_dispatch.md b/docs/implicit_conversion_dispatch.md
index 5f946fe6..ae57ffc9 100644
--- a/docs/implicit_conversion_dispatch.md
+++ b/docs/implicit_conversion_dispatch.md
@@ -22,7 +22,6 @@ Class `implicit_conversion_dispatch` models a [dispatch](ProDispatch.md) type fo
 ## Example
 
 ```cpp
-#include <iomanip>
 #include <iostream>
 
 #include "proxy.h"
diff --git a/docs/inplace_proxiable_target.md b/docs/inplace_proxiable_target.md
index f431473d..22e182ed 100644
--- a/docs/inplace_proxiable_target.md
+++ b/docs/inplace_proxiable_target.md
@@ -2,10 +2,10 @@
 
 ```cpp
 template <class T, class F>
-concept inplace_proxiable_target = proxiable</* inplace-ptr<T> */, F>;
+concept inplace_proxiable_target = proxiable<inplace-ptr<T>, F>;
 ```
 
-The concept `inplace_proxiable_target<T, F>` specifies that a value type `T`, when wrapped by an implementation-defined non-allocating pointer type, models a contained value type of [`proxy<F>`](proxy.md). The size and alignment of this implementation-defined pointer type are guaranteed to be equal to those of type `T`.
+See [`make_proxy_inplace`](make_proxy_inplace.md) for the definition of the exposition-only class template *inplace-ptr*.
 
 ## Example
 
@@ -31,4 +31,4 @@ int main() {
 ## See Also
 
 - [concept `proxiable`](proxiable.md)
-- [function template `make_proxy_inplacce`](make_proxy_inplace.md)
+- [concept `proxiable_target`](proxiable_target.md)
diff --git a/docs/make_proxy.md b/docs/make_proxy.md
index ff1d2590..07482bd1 100644
--- a/docs/make_proxy.md
+++ b/docs/make_proxy.md
@@ -3,12 +3,12 @@
 The definitions of `make_proxy` make use of the following exposition-only function:
 
 ```cpp
-template <class F, class T, class... Args>
+template <facade F, class T, class... Args>
 proxy<F> make-proxy-internal(Args&&... args) {
   if constexpr (inplace_proxiable_target<T, F>) {
     return make_proxy_inplace<F, T>(std::forward<Args>(args)...);
   } else {
-    return allocate_proxy<F, T>(std::allocator<T>{}, std::forward<Args>(args)...);
+    return allocate_proxy<F, T>(std::allocator<void>{}, std::forward<Args>(args)...);
   }
 }
 ```
@@ -33,6 +33,8 @@ proxy<F> make_proxy(T&& value);  // freestanding-deleted
 
 `(3)` Equivalent to `return make-proxy-internal<F, std::decay_t<T>>(std::forward<T>(value))`.
 
+*Since 3.3.0*: For `(1-3)`, if [`proxiable_target<std::decay_t<T>, F>`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated.
+
 ## Return Value
 
 The constructed `proxy` object.
diff --git a/docs/make_proxy_inplace.md b/docs/make_proxy_inplace.md
index 1110a890..c2143c5c 100644
--- a/docs/make_proxy_inplace.md
+++ b/docs/make_proxy_inplace.md
@@ -1,31 +1,35 @@
 # Function template `make_proxy_inplace`
 
-The definition of `make_proxy_inplace` makes use of an exposition-only class template *sbo-ptr*. Similar to [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional), `sbo-ptr<T>` contains the storage for an object of type `T`, manages its lifetime, and provides `operator*` for access with the same qualifiers. However, it does not necessarily support the state where the contained object is absent. `sbo-ptr<T>` has the same size and alignment as `T`.
+The definition of `make_proxy_inplace` makes use of an exposition-only class template *inplace-ptr*. Similar to [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional), `inplace-ptr<T>` contains the storage for an object of type `T`, manages its lifetime, and provides `operator*` for access with the same qualifiers. However, it does not necessarily support the state where the contained object is absent. `inplace-ptr<T>` has the same size and alignment as `T`.
 
 ```cpp
 // (1)
-template <facade F, inplace_proxiable_target<F> T, class... Args>
+template <facade F, class T, class... Args>
 proxy<F> make_proxy_inplace(Args&&... args)
-    noexcept(std::is_nothrow_constructible_v<T, Args...>);
+    noexcept(std::is_nothrow_constructible_v<T, Args...>)
+    requires(std::is_constructible_v<T, Args...>);
 
 // (2)
-template <facade F, inplace_proxiable_target<F> T, class U, class... Args>
+template <facade F, class T, class U, class... Args>
 proxy<F> make_proxy_inplace(std::initializer_list<U> il, Args&&... args)
     noexcept(std::is_nothrow_constructible_v<
-        T, std::initializer_list<U>&, Args...>);
+        T, std::initializer_list<U>&, Args...>)
+    requires(std::is_constructible_v<T, std::initializer_list<U>&, Args...>);
 
 // (3)
 template <facade F, class T>
 proxy<F> make_proxy_inplace(T&& value)
     noexcept(std::is_nothrow_constructible_v<std::decay_t<T>, T>)
-    requires(inplace_proxiable_target<std::decay_t<T>, F>);
+    requires(std::is_constructible_v<std::decay_t<T>, T>);
 ```
 
-`(1)` Creates a `proxy<F>` object containing a value `p` of type `sbo-ptr<T>`, where `*p` is direct-non-list-initialized with `std::forward<Args>(args)...`.
+`(1)` Creates a `proxy<F>` object containing a value `p` of type `inplace-ptr<T>`, where `*p` is direct-non-list-initialized with `std::forward<Args>(args)...`.
 
-`(2)` Creates a `proxy<F>` object containing a value `p` of type `sbo-ptr<T>`, where `*p` is direct-non-list-initialized with `il, std::forward<Args>(args)...`.
+`(2)` Creates a `proxy<F>` object containing a value `p` of type `inplace-ptr<T>`, where `*p` is direct-non-list-initialized with `il, std::forward<Args>(args)...`.
 
-`(3)` Creates a `proxy<F>` object containing a value `p` of type `sbo-ptr<std::decay_t<T>>`, where `*p` is direct-non-list-initialized with `std::forward<T>(value)`.
+`(3)` Creates a `proxy<F>` object containing a value `p` of type `inplace-ptr<std::decay_t<T>>`, where `*p` is direct-non-list-initialized with `std::forward<T>(value)`.
+
+*Since 3.3.0*: For `(1-3)`, if [`inplace_proxiable_target<std::decay_t<T>, F>`](inplace_proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated.
 
 ## Return Value
 
diff --git a/docs/make_proxy_shared.md b/docs/make_proxy_shared.md
new file mode 100644
index 00000000..c6a5f7d0
--- /dev/null
+++ b/docs/make_proxy_shared.md
@@ -0,0 +1,63 @@
+# Function template `make_proxy_shared`
+
+```cpp
+// (1)
+template <facade F, class T, class... Args>
+proxy<F> make_proxy_shared(Args&&... args);  // freestanding-deleted
+
+// (2)
+template <facade F, class T, class U, class... Args>
+proxy<F> make_proxy_shared(std::initializer_list<U> il, Args&&... args);  // freestanding-deleted
+
+// (3)
+template <facade F, class T>
+proxy<F> make_proxy_shared(T&& value);  // freestanding-deleted
+```
+
+`(1)` Equivalent to `return allocate_proxy_shared<F, T>(std::allocator<void>{}, std::forward<Args>(args)...)`.
+
+`(2)` Equivalent to `return allocate_proxy_shared<F, T>(std::allocator<void>{}, il, std::forward<Args>(args)...)`.
+
+`(3)` Equivalent to `return allocate_proxy_shared<F, std::decay_t<T>>(std::allocator<void>{}, std::forward<T>(value))`.
+
+*Since 3.3.0*: For `(1-3)`, if [`proxiable_target<std::decay_t<T>, F>`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated.
+
+## Return Value
+
+The constructed `proxy` object.
+
+## Exceptions
+
+Throws any exception thrown by allocation and the constructor of `T`.
+
+## Example
+
+```cpp
+#include <iostream>
+
+#include "proxy.h"
+
+struct RttiAware : pro::facade_builder
+    ::support_copy<pro::constraint_level::nothrow>
+    ::support_rtti
+    ::support_weak
+    ::build {};
+
+int main() {
+  pro::proxy<RttiAware> p1 = pro::make_proxy_shared<RttiAware>(123);
+  pro::weak_proxy<RttiAware> p2 = p1;
+  pro::proxy<RttiAware> p3 = p2.lock();
+  std::cout << std::boolalpha << p3.has_value() << "\n";  // Prints "true"
+  std::cout << proxy_cast<int>(*p3) << "\n";  // Prints "123"
+
+  p3.reset();
+  p1.reset();
+  p3 = p2.lock();
+  std::cout << std::boolalpha << p3.has_value() << "\n";  // Prints "false"
+}
+```
+
+## See Also
+
+- [function template `make_proxy`](make_proxy.md)
+- [function template `allocate_proxy_shared`](allocate_proxy_shared.md)
diff --git a/docs/make_proxy_view.md b/docs/make_proxy_view.md
new file mode 100644
index 00000000..9316049a
--- /dev/null
+++ b/docs/make_proxy_view.md
@@ -0,0 +1,46 @@
+# Function template `make_proxy_view`
+
+The definition of `make_proxy_view` makes use of an exposition-only class template *observer-ptr*. `observer-ptr<T>` contains a raw pointer to an object of type `T`, and provides `operator*` for access with the same qualifiers.
+
+```cpp
+template <facade F, class T>
+proxy_view<F> make_proxy_view(T& value) noexcept;
+```
+
+Creates a `proxy_view<F>` object containing a value `p` of type `observer-ptr<T>`, where `*p` is direct-non-list-initialized with `&value`. If [`proxiable_target<T, F>`](proxiable_target.md) is `false`, the program is ill-formed and diagnostic messages are generated.
+
+## Return Value
+
+The constructed `proxy_view` object.
+
+## Example
+
+```cpp
+#include <iostream>
+#include <map>
+#include <string>
+
+#include "proxy.h"
+
+PRO_DEF_MEM_DISPATCH(MemAt, at);
+
+struct ResourceDictionary : pro::facade_builder
+    ::add_convention<MemAt, std::string&(int index), const std::string&(int index) const>
+    ::build {};
+
+int main() {
+  std::map<int, std::string> dict;
+  dict[1] = "init";
+  pro::proxy_view<ResourceDictionary> pv = pro::make_proxy_view<ResourceDictionary>(dict);
+  static_assert(std::is_same_v<decltype(pv->at(1)), std::string&>, "Non-const overload");
+  static_assert(std::is_same_v<decltype(std::as_const(pv)->at(1)), const std::string&>, "Const overload");
+  std::cout << std::as_const(pv)->at(1) << "\n";  // Invokes the const overload and prints "init"
+  pv->at(1) = "modified";  // Invokes the non-const overload
+  std::cout << std::as_const(pv)->at(1) << "\n";  // Invokes the const overload and prints "modified"
+}
+```
+
+## See Also
+
+- [concept `proxiable_target`](proxiable_target.md)
+- [`basic_facade_builder::support_view`](basic_facade_builder/support_view.md)
\ No newline at end of file
diff --git a/docs/msft_lib_proxy.md b/docs/msft_lib_proxy.md
index 59bb5df0..9b8836c3 100644
--- a/docs/msft_lib_proxy.md
+++ b/docs/msft_lib_proxy.md
@@ -8,6 +8,7 @@ Similar to the standard [feature test macros](https://en.cppreference.com/w/cpp/
 
 | Version | Value of `__msft_lib_proxy` |
 | ------- | --------------------------- |
+| 3.3.0   | `202503L`                   |
 | 3.2.1   | `202502L`                   |
 | 3.2.0   | `202501L`                   |
 | 3.1.0   | `202410L`                   |
diff --git a/docs/proxiable.md b/docs/proxiable.md
index 1ec03f29..70bcb12f 100644
--- a/docs/proxiable.md
+++ b/docs/proxiable.md
@@ -5,7 +5,7 @@ template <class P, class F>
 concept proxiable = /* see-below */;
 ```
 
-The concept `proxiable<P, F>` specifies that [`proxy<F>`](proxy.md) can potentially contain a value of type `P`. For a type `P`, if `P` is an incomplete type, the behavior of evaluating `proxiable<P, F>` is undefined. `proxiable<P, F>` is `true` when `F` meets the [*ProFacade* requirements](ProFacade.md) of `P`; otherwise, it is `false`.
+The concept `proxiable<P, F>` specifies that [`proxy<F>`](proxy.md) can potentially contain a value of type `P`. If `P` is an incomplete type, the behavior of evaluating `proxiable<P, F>` is undefined. `proxiable<P, F>` is `true` when `F` meets the [*ProFacade* requirements](ProFacade.md) of `P`; otherwise, it is `false`.
 
 ## Example
 
diff --git a/docs/proxiable_target.md b/docs/proxiable_target.md
new file mode 100644
index 00000000..c077c28a
--- /dev/null
+++ b/docs/proxiable_target.md
@@ -0,0 +1,29 @@
+# Concept `proxiable_target`
+
+```cpp
+template <class T, class F>
+concept proxiable_target = proxiable<observer-ptr<T>, F>;
+```
+
+See [`make_proxy_view`](make_proxy_view.md) for the definition of the exposition-only class template *observer-ptr*.
+
+## Example
+
+```cpp
+#include "proxy.h"
+
+struct Runnable : pro::facade_builder
+    ::add_convention<pro::operator_dispatch<"()">, void()>
+    ::build {};
+
+int main() {
+  auto fun = [] {};
+  static_assert(pro::proxiable_target<decltype(fun), Runnable>);
+  static_assert(!pro::proxiable_target<int, Runnable>);
+}
+```
+
+## See Also
+
+- [concept `proxiable`](proxiable.md)
+- [concept `inplace_proxiable_target`](inplace_proxiable_target.md)
diff --git a/docs/proxy.md b/docs/proxy.md
index 42efebfb..68559a16 100644
--- a/docs/proxy.md
+++ b/docs/proxy.md
@@ -1,13 +1,13 @@
 # Class template `proxy`
 
 ```cpp
-template <class F>
+template <facade F>
 class proxy;
 ```
 
 Class template `proxy` is a general-purpose polymorphic wrapper for C++ objects. Unlike other polymorphic wrappers in the C++ standard (e.g., [`std::function`](https://en.cppreference.com/w/cpp/utility/functional/function), [`std::move_only_function`](https://en.cppreference.com/w/cpp/utility/functional/move_only_function), [`std::any`](https://en.cppreference.com/w/cpp/utility/any), etc.), `proxy` is based on pointer semantics. It supports flexible lifetime management without runtime [garbage collection (GC)](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)), and offers best-in-class code generation quality, extendibility and accessibility.
 
-To instantiate `proxy<F>`, `F` shall model [concept `facade`](facade.md). As per `facade<F>`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Cs`, and `typename F::reflection_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Rs`. For each type `T` in `Cs` or `Rs`, if `T` meets the [*ProAccessible* requirements](ProAccessible.md) of `F`, `typename T::template accessor<F>` is inherited by `proxy<F>` when `T::is_direct` is `true`. Otherwise, it is inherited by [`proxy_indirect_accessor`](proxy_indirect_accessor.md), the return type of [`operator*`](proxy/indirection.md), when `T::is_direct` is `false`. Implementation of accessors can call [`access_proxy`](access_proxy.md) to access the `proxy` object. It is recommended to use [`facade_builder`](basic_facade_builder.md) to define a facade type.
+As per `facade<F>`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Cs`, and `typename F::reflection_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Rs`. For each type `T` in `Cs` or `Rs`, if `T` meets the [*ProAccessible* requirements](ProAccessible.md) of `F`, `typename T::template accessor<F>` is inherited by `proxy<F>` when `T::is_direct` is `true`. Otherwise, it is inherited by [`proxy_indirect_accessor`](proxy_indirect_accessor.md), the return type of [`operator*`](proxy/indirection.md), when `T::is_direct` is `false`. Implementation of accessors can call [`access_proxy`](access_proxy.md) to access the `proxy` object. It is recommended to use [`facade_builder`](basic_facade_builder.md) to define a facade type.
 
 Any instance of `proxy<F>` at any given point in time either *contains a value* or *does not contain a value*. If a `proxy<F>` *contains a value*, the type of the value shall be a pointer type `P`  where [`proxiable<P, F>`](proxiable.md) is `true`, and the value is guaranteed to be allocated as part of the `proxy` object footprint, i.e. no dynamic memory allocation occurs. However, `P` may allocate during its construction, depending on its implementation.
 
diff --git a/docs/proxy/assignment.md b/docs/proxy/assignment.md
index d0954252..660e6b62 100644
--- a/docs/proxy/assignment.md
+++ b/docs/proxy/assignment.md
@@ -29,8 +29,7 @@ template <class P>
 proxy& operator=(P&& ptr)
     noexcept(std::is_nothrow_constructible_v<std::decay_t<P>, P> &&
         F::constraints.destructibility >= constraint_level::nothrow)
-    requires(proxiable<std::decay_t<P>, F> &&
-        std::is_constructible_v<std::decay_t<P>, P> &&
+    requires(std::is_constructible_v<std::decay_t<P>, P> &&
         F::constraints.destructibility >= constraint_level::nontrivial);
 ```
 
@@ -39,7 +38,7 @@ Assigns a new value to `proxy` or destroys the contained value.
 - `(1)` Destroys the current contained value if it exists. After the call, `*this` does not contain a value.
 - `(2)` Copy assignment operator copies the contained value of `rhs` to `*this`. If `rhs` does not contain a value, it destroys the contained value of `*this` (if any) as if by `auto(rhs).swap(*this)`. The copy assignment is trivial when `F::constraints.copyability == constraint_level::trivial` is `true`.
 - `(3)` Move assignment operator moves the contained value of `rhs` to `*this`. If `rhs` does not contain a value, it destroys the contained value of `*this` (if any). If the move construction throws when `F::constraints.relocatability == constraint_level::nontrivial`, `*this` does not contain a value. After move assignment, `rhs` is in a valid state with an unspecified value. The move assignment operator does not participate in overload resolution when `F::constraints.copyability == constraint_level::trivial`, falling back to the trivial copy assignment operator.
-- `(4)` Let `VP` be `std::decay_t<P>`. Sets the contained value to an object of type `VP`, direct-non-list-initialized with `std::forward<P>(ptr)`.
+- `(4)` Let `VP` be `std::decay_t<P>`. Sets the contained value to an object of type `VP`, direct-non-list-initialized with `std::forward<P>(ptr)`. This overload participates in overload resolution only if `std::decay_t<P>` is not a specialization of `proxy`. *Since 3.3.0*: If [`proxiable<VP, F>`](../proxiable.md) is `false`, the program is ill-formed and diagnostic messages are generated.
 
 ## Return Value
 
diff --git a/docs/proxy/constructor.md b/docs/proxy/constructor.md
index a3fafed1..d3f1df2c 100644
--- a/docs/proxy/constructor.md
+++ b/docs/proxy/constructor.md
@@ -22,17 +22,16 @@ proxy(proxy&& rhs)
 // (4)
 template <class P>
 proxy(P&& ptr) noexcept(std::is_nothrow_constructible_v<std::decay_t<P>, P>)
-    requires(proxiable<std::decay_t<P>, F> &&
-        std::is_constructible_v<std::decay_t<P>, P>);
+    requires(std::is_constructible_v<std::decay_t<P>, P>);
 
 // (5)
-template <proxiable<F> P, class... Args>
+template <class P, class... Args>
 explicit proxy(std::in_place_type_t<P>, Args&&... args)
     noexcept(std::is_nothrow_constructible_v<P, Args...>)
     requires(std::is_constructible_v<P, Args...>);
 
 // (6)
-template <proxiable<F> P, class U, class... Args>
+template <class P, class U, class... Args>
 explicit proxy(std::in_place_type_t<P>, std::initializer_list<U> il,
         Args&&... args)
     noexcept(std::is_nothrow_constructible_v<
@@ -45,10 +44,12 @@ Creates a new `proxy`.
 - `(1)` Default constructor and the constructor taking `nullptr` construct a `proxy` that does not contain a value.
 - `(2)` Copy constructor constructs a `proxy` whose contained value is that of `rhs` if `rhs` contains a value, or otherwise, constructs a `proxy` that does not contain a value. As per the `requires` clause, the copy constructor is trivial when `F::constraints.copyability == constraint_level::trivial`.
 - `(3)` Move constructor constructs a `proxy` whose contained value is that of `rhs` if `rhs` contains a value, or otherwise, constructs a `proxy` that does not contain a value. `rhs` is in a valid but unspecified state after move construction. As per the `requires` clause, the move constructor does not participate in overload resolution when `F::constraints.copyability == constraint_level::trivial`, so that a move construction falls back to the trivial copy constructor.
-- `(4)` Let `VP` be `std::decay_t<P>`. Constructor taking a value of pointer constructs a `proxy` whose contained value is of type `VP` and direct-non-list-initialized with `std::forward<P>(ptr)`. This overload participates in overload resolution only if `std::decay_t<P>` is not the same type as `proxy` nor a specialization of `std::in_place_type_t`.
+- `(4)` Let `VP` be `std::decay_t<P>`. Constructor taking a value of pointer constructs a `proxy` whose contained value is of type `VP` and direct-non-list-initialized with `std::forward<P>(ptr)`. This overload participates in overload resolution only if `std::decay_t<P>` is not a specialization of `proxy` nor a specialization of `std::in_place_type_t`.
 - `(5)` Constructs a `proxy` whose contained value is of type `P` and direct-non-list-initialized with `std::forward<Args>(args)...`.
 - `(6)` Constructs a `proxy` whose contained value is of type `P` and direct-non-list-initialized with `il, std::forward<Args>(args)...`.
 
+*Since 3.3.0*: For `(4-6)`, if [`proxiable<std::decay_t<P>, F>`](../proxiable.md) is `false`, the program is ill-formed and diagnostic messages are generated.
+
 ## Comparing with Other Standard Polymorphic Wrappers
 
 The constructors of `proxy<F>` are similar to but have certain differences from other polymorphic wrappers in the standard, specifically, [`std::any`](https://en.cppreference.com/w/cpp/utility/any/any), and [`std::move_only_function`](https://en.cppreference.com/w/cpp/utility/functional/move_only_function/move_only_function).
diff --git a/docs/proxy/emplace.md b/docs/proxy/emplace.md
index 971b386f..3225528e 100644
--- a/docs/proxy/emplace.md
+++ b/docs/proxy/emplace.md
@@ -2,7 +2,7 @@
 
 ```cpp
 // (1)
-template <proxiable<F> P, class... Args>
+template <class P, class... Args>
 P& emplace(Args&&... args)
     noexcept(std::is_nothrow_constructible_v<P, Args...> &&
         F::constraints.destructibility >= constraint_level::nothrow)
@@ -10,7 +10,7 @@ P& emplace(Args&&... args)
         F::constraints.destructibility >= constraint_level::nontrivial);
 
 // (2)
-template <proxiable<F> P, class U, class... Args>
+template <class P, class U, class... Args>
 P& emplace(std::initializer_list<U> il, Args&&... args)
     noexcept(std::is_nothrow_constructible_v<
         P, std::initializer_list<U>&, Args...> &&
@@ -26,6 +26,8 @@ First, the current contained value (if any) is destroyed as if by calling [reset
 - `(1)` Sets the contained value to an object of type `P` and direct-non-list-initialized with `std::forward<Args>(args)...`.
 - `(2)` Sets the contained value to an object of type `P` and direct-non-list-initialized with `il, std::forward<Args>(args)...`.
 
+*Since 3.3.0*: For `(1-2)`, if [`proxiable<P, F>`](../proxiable.md) is `false`, the program is ill-formed and diagnostic messages are generated.
+
 ## Return Value
 
 A reference to the newly created contained value.
diff --git a/docs/proxy_indirect_accessor.md b/docs/proxy_indirect_accessor.md
index 9e637889..b41b2765 100644
--- a/docs/proxy_indirect_accessor.md
+++ b/docs/proxy_indirect_accessor.md
@@ -1,11 +1,11 @@
 # Class template `proxy_indirect_accessor`
 
 ```cpp
-template <class F>
+template <facade F>
 class proxy_indirect_accessor;  // since 3.2.0
 ```
 
-Class template `proxy_indirect_accessor` provides indirection accessibility for `proxy`. To instantiate `proxy_indirect_accessor<F>`, `F` shall model [concept `facade`](facade.md). As per `facade<F>`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Cs`, and `typename F::reflection_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Rs`. For each type `T` in `Cs` or `Rs`, if `T` meets the [*ProAccessible* requirements](ProAccessible.md) of `F` and `T::is_direct` is `false`, `typename T::template accessor<F>` is inherited by `proxy_indirect_accessor<F>`.
+Class template `proxy_indirect_accessor` provides indirection accessibility for `proxy`. As per `facade<F>`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Cs`, and `typename F::reflection_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Rs`. For each type `T` in `Cs` or `Rs`, if `T` meets the [*ProAccessible* requirements](ProAccessible.md) of `F` and `T::is_direct` is `false`, `typename T::template accessor<F>` is inherited by `proxy_indirect_accessor<F>`.
 
 ## Member Functions
 
@@ -15,4 +15,4 @@ Class template `proxy_indirect_accessor` provides indirection accessibility for
 
 ## See also
 
-[function template `access_proxy`](access_proxy.md)
+- [function template `access_proxy`](access_proxy.md)
diff --git a/docs/proxy_invoke.md b/docs/proxy_invoke.md
index d78481e6..61ea063e 100644
--- a/docs/proxy_invoke.md
+++ b/docs/proxy_invoke.md
@@ -1,16 +1,16 @@
 # Function template `proxy_invoke`
 
 ```cpp
-template <bool IsDirect, class D, class O, class F, class... Args>
+template <bool IsDirect, class D, class O, facade F, class... Args>
 /* see below */ proxy_invoke(proxy<F>& p, Args&&... args);
 
-template <bool IsDirect, class D, class O, class F, class... Args>
+template <bool IsDirect, class D, class O, facade F, class... Args>
 /* see below */ proxy_invoke(const proxy<F>& p, Args&&... args);
 
-template <bool IsDirect, class D, class O, class F, class... Args>
+template <bool IsDirect, class D, class O, facade F, class... Args>
 /* see below */ proxy_invoke(proxy<F>&& p, Args&&... args);
 
-template <bool IsDirect, class D, class O, class F, class... Args>
+template <bool IsDirect, class D, class O, facade F, class... Args>
 /* see below */ proxy_invoke(const proxy<F>&& p, Args&&... args);
 ```
 
diff --git a/docs/proxy_reflect.md b/docs/proxy_reflect.md
index ea8bc418..6e08849f 100644
--- a/docs/proxy_reflect.md
+++ b/docs/proxy_reflect.md
@@ -1,7 +1,7 @@
 # Function template `proxy_reflect`
 
 ```cpp
-template <bool IsDirect, class R, class F>
+template <bool IsDirect, class R, facade F>
 const R& proxy_reflect(const proxy<F>& p) noexcept;
 ```
 
diff --git a/docs/proxy_view.md b/docs/proxy_view.md
index 195d1a50..be7e1292 100644
--- a/docs/proxy_view.md
+++ b/docs/proxy_view.md
@@ -1,14 +1,14 @@
 # Alias template `proxy_view`<br />Class template `observer_facade`
 
 ```cpp
-template <class F>
+template <facade F>
 struct observer_facade;  // since 3.2.0
 
-template <class F>
+template <facade F>
 using proxy_view = proxy<observer_facade<F>>;  // since 3.2.0
 ```
 
-Class template `observer_facade` is a [facade](facade.md) type for observer pointers (e.g., raw pointers) potentially dereferenced from a `proxy` object. To instantiate `observer_facade<F>`, `F` shall model [concept `facade`](facade.md).
+Class template `observer_facade` is a [facade](facade.md) type for observer pointers (e.g., raw pointers) potentially dereferenced from a `proxy` object.
 
 ## Member Types of `observer_facade`
 
@@ -45,4 +45,5 @@ int main() {
 
 ## See Also
 
-[`basic_facade_builder::support_view`](basic_facade_builder/support_view.md)
+- [`basic_facade_builder::support_view`](basic_facade_builder/support_view.md)
+- [function template `make_proxy_view`](make_proxy_view.md)
diff --git a/docs/specifications.md b/docs/specifications.md
index b36cace7..bb7724f7 100644
--- a/docs/specifications.md
+++ b/docs/specifications.md
@@ -4,11 +4,12 @@ This document provides the API specifications for the C++ library Proxy (version
 
 ## Concepts
 
-| Name                                                      | Description                                                  |
-| --------------------------------------------------------- | ------------------------------------------------------------ |
-| [`facade`](facade.md)                                     | Specifies that a type models a "facade"                      |
-| [`inplace_proxiable_target`](inplace_proxiable_target.md) | Specifies that a value type can instantiate a `proxy` without allocation |
-| [`proxiable`](proxiable.md)                               | Specifies that a pointer type can instantiate a `proxy`      |
+| Name                                                         | Description                                                  |
+| ------------------------------------------------------------ | ------------------------------------------------------------ |
+| [`facade`](facade.md)                                        | Specifies that a type models a "facade"                      |
+| [`inplace_proxiable_target`](inplace_proxiable_target.md)    | Specifies that a value type can instantiate a `proxy` without allocation |
+| [`proxiable_target`](proxiable_target.md)<br />*(since 3.3.0)* | Specifies that a reference type can instantiate a `proxy_view` |
+| [`proxiable`](proxiable.md)                                  | Specifies that a pointer type can instantiate a `proxy`      |
 
 ## Classes
 
@@ -24,21 +25,25 @@ This document provides the API specifications for the C++ library Proxy (version
 | [`operator_dispatch`](operator_dispatch.md)                  | Dispatch type for operator expressions with accessibility    |
 | [`proxiable_ptr_constraints`](proxiable_ptr_constraints.md)  | Defines the constraints of a pointer type to instantiate a `proxy` |
 | [`proxy_indirect_accessor`](proxy_indirect_accessor.md)<br />*(since 3.2.0)* | Provides indirection accessibility for `proxy`               |
-| [`proxy_view`<br />`observer_facade`](proxy_view.md)<br />*(since 3.2.0)* | Non-owning proxy optimized for raw pointers                  |
+| [`proxy_view`<br />`observer_facade`](proxy_view.md)<br />*(since 3.2.0)* | Non-owning `proxy` optimized for raw pointer types           |
 | [`proxy`](proxy.md)                                          | Wraps a pointer object matching specified facade             |
 | [`std::formatter<proxy_indirect_accessor>`](formatter_proxy_indirect_accessor.md)<br />*(since 3.2.0)* | Formatting support for `proxy_indirect_accessor`             |
 | [`weak_dispatch`](weak_dispatch.md)<br />*(since 3.2.0)*     | Weak dispatch type with a default implementation that throws `not_implemented` |
+| [`weak_proxy`<br />`weak_facade`](weak_proxy.md)<br />*(since 3.3.0)* | `proxy` with weak ownership                                  |
 
 ## Functions
 
-| Name                                          | Description                                                  |
-| --------------------------------------------- | ------------------------------------------------------------ |
-| [`access_proxy`](access_proxy.md)             | Accesses a `proxy` object via an accessor                    |
-| [`allocate_proxy`](allocate_proxy.md)         | Creates a `proxy` object with an allocator                   |
-| [`make_proxy_inplace`](make_proxy_inplace.md) | Creates a `proxy` object with strong no-allocation guarantee |
-| [`make_proxy`](make_proxy.md)                 | Creates a `proxy` object potentially with heap allocation    |
-| [`proxy_invoke`](proxy_invoke.md)             | Invokes a `proxy` with a specified convention                |
-| [`proxy_reflect`](proxy_reflect.md)           | Acquires reflection information of the underlying pointer type |
+| Name                                                         | Description                                                  |
+| ------------------------------------------------------------ | ------------------------------------------------------------ |
+| [`access_proxy`](access_proxy.md)                            | Accesses a `proxy` object via an accessor                    |
+| [`allocate_proxy_shared`](allocate_proxy_shared.md)<br />*(since 3.3.0)* | Creates a `proxy` object with shared ownership using an allocator |
+| [`allocate_proxy`](allocate_proxy.md)                        | Creates a `proxy` object with an allocator                   |
+| [`make_proxy_inplace`](make_proxy_inplace.md)                | Creates a `proxy` object with strong no-allocation guarantee |
+| [`make_proxy_shared`](make_proxy_shared.md)<br />*(since 3.3.0)* | Creates a `proxy` object with shared ownership               |
+| [`make_proxy_view`](make_proxy_view.md)<br />*(since 3.3.0)* | Creates a `proxy_view` object                                |
+| [`make_proxy`](make_proxy.md)                                | Creates a `proxy` object potentially with heap allocation    |
+| [`proxy_invoke`](proxy_invoke.md)                            | Invokes a `proxy` with a specified convention                |
+| [`proxy_reflect`](proxy_reflect.md)                          | Acquires reflection information of the underlying pointer type |
 
 ## Macros
 
diff --git a/docs/weak_proxy.md b/docs/weak_proxy.md
new file mode 100644
index 00000000..d37662ef
--- /dev/null
+++ b/docs/weak_proxy.md
@@ -0,0 +1,54 @@
+# Alias template `weak_proxy`<br />Class template `weak_facade`
+
+```cpp
+template <facade F>
+struct weak_facade;  // since 3.3.0
+
+template <facade F>
+using weak_proxy = proxy<weak_facade<F>>;  // since 3.3.0
+```
+
+Class template `weak_facade` is a [facade](facade.md) type for weak pointers (e.g., [`std::weak_ptr`](https://en.cppreference.com/w/cpp/memory/weak_ptr)) potentially converted from a `proxy` object.
+
+## Member Types of `observer_facade`
+
+| Name               | Description                                                  |
+| ------------------ | ------------------------------------------------------------ |
+| `convention_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains one convention type `C`, where`C::is_direct` is `false`, `C::dispatch_type` is of member function `lock` with accessibility, and `C::overload_types` is a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains type `proxy<F>() const noexcept`. |
+| `reflection_types` | A [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type that contains no types. |
+
+## Member Constants of `observer_facade`
+
+| Name                               | Description                    |
+| ---------------------------------- | ------------------------------ |
+| `constraints` [static] [constexpr] | Equivalent to `F::constraints` |
+
+## Example
+
+```cpp
+#include <iostream>
+
+#include "proxy.h"
+
+struct Formattable : pro::facade_builder
+    ::support_format
+    ::build {};
+
+int main() {
+  std::shared_ptr<int> val = std::make_shared<int>(123);
+  pro::weak_proxy<Formattable> wp = std::weak_ptr{val};
+  pro::proxy<Formattable> p = wp.lock();
+  std::cout << std::boolalpha << p.has_value() << "\n";  // Prints "true"
+  std::cout << std::format("{}\n", *p);  // Prints "123"
+
+  p.reset();
+  val.reset();
+  p = wp.lock();
+  std::cout << p.has_value() << "\n";  // Prints "false"
+}
+```
+
+## See Also
+
+- [`basic_facade_builder::support_weak`](basic_facade_builder/support_weak.md)
+- [function template `make_proxy_shared`](make_proxy_shared.md)
diff --git a/proxy.h b/proxy.h
index 044ba181..9ba1c9e2 100644
--- a/proxy.h
+++ b/proxy.h
@@ -59,7 +59,7 @@
 #define ___PRO_DEBUG(...) __VA_ARGS__
 #endif  // NDEBUG
 
-#define __msft_lib_proxy 202502L
+#define __msft_lib_proxy 202503L
 
 namespace pro {
 
@@ -2508,7 +2508,7 @@ struct weak_dispatch : D {
 #if __STDC_HOSTED__
 namespace std {
 
-template <class F, class CharT>
+template <pro::facade F, class CharT>
     requires(pro::details::facade_traits<F>::template is_invocable<false,
         pro::details::format_dispatch, pro::details::format_overload_t<CharT>>)
 struct formatter<pro::proxy_indirect_accessor<F>, CharT> {
diff --git a/samples/allocate_proxy_shared.cpp b/samples/allocate_proxy_shared.cpp
new file mode 100644
index 00000000..41032aa8
--- /dev/null
+++ b/samples/allocate_proxy_shared.cpp
@@ -0,0 +1,22 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+// This file contains example code from allocate_proxy_shared.md.
+
+#include <iostream>
+#include <memory_resource>
+
+#include "proxy.h"
+
+struct RttiAware : pro::facade_builder
+    ::support_copy<pro::constraint_level::nothrow>
+    ::support_rtti
+    ::build {};
+
+int main() {
+  std::pmr::unsynchronized_pool_resource pool;
+  std::pmr::polymorphic_allocator<> alloc{&pool};
+  pro::proxy<RttiAware> p1 = pro::allocate_proxy_shared<RttiAware>(alloc, 1);
+  pro::proxy<RttiAware> p2 = p1;
+  proxy_cast<int&>(*p1) += 2;
+  std::cout << proxy_cast<int>(*p2) << "\n";  // Prints "3"
+}
diff --git a/samples/basic_facade_builder/support_weak.cpp b/samples/basic_facade_builder/support_weak.cpp
new file mode 100644
index 00000000..4f699098
--- /dev/null
+++ b/samples/basic_facade_builder/support_weak.cpp
@@ -0,0 +1,25 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+// This file contains example code from support_weak.md.
+
+#include <iostream>
+
+#include "proxy.h"
+
+struct Formattable : pro::facade_builder
+    ::support_format
+    ::support_weak
+    ::build {};
+
+int main() {
+  pro::proxy<Formattable> p1 = pro::make_proxy_shared<Formattable>(123);
+  pro::weak_proxy<Formattable> wp = p1;
+  pro::proxy<Formattable> p2 = wp.lock();
+  std::cout << std::boolalpha << p2.has_value() << "\n";  // Prints "true"
+  std::cout << std::format("{}\n", *p2);  // Prints "123"
+
+  p1.reset();
+  p2.reset();
+  p2 = wp.lock();
+  std::cout << p2.has_value() << "\n";  // Prints "false"
+}
diff --git a/samples/facade_aware_overload_t.cpp b/samples/facade_aware_overload_t.cpp
index 0b0b34b9..e916560b 100644
--- a/samples/facade_aware_overload_t.cpp
+++ b/samples/facade_aware_overload_t.cpp
@@ -9,7 +9,7 @@
 template <class F>
 using BinaryOverload = pro::proxy<F>(const pro::proxy_indirect_accessor<F>& rhs) const;
 
-template <class T, class F>
+template <class T, pro::facade F>
 pro::proxy<F> operator+(const T& value, const pro::proxy_indirect_accessor<F>& rhs)
     requires(!std::is_same_v<T, pro::proxy_indirect_accessor<F>>)
     { return pro::make_proxy<F, T>(value + proxy_cast<const T&>(rhs)); }
diff --git a/samples/implicit_conversion_dispatch.cpp b/samples/implicit_conversion_dispatch.cpp
index ad03f10d..e818ab68 100644
--- a/samples/implicit_conversion_dispatch.cpp
+++ b/samples/implicit_conversion_dispatch.cpp
@@ -2,7 +2,6 @@
 // Licensed under the MIT License.
 // This file contains example code from implicit_conversion_dispatch.md.
 
-#include <iomanip>
 #include <iostream>
 
 #include "proxy.h"
diff --git a/samples/make_proxy_shared.cpp b/samples/make_proxy_shared.cpp
new file mode 100644
index 00000000..7fade471
--- /dev/null
+++ b/samples/make_proxy_shared.cpp
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+// This file contains example code from make_proxy_shared.md.
+
+#include <iostream>
+
+#include "proxy.h"
+
+struct RttiAware : pro::facade_builder
+    ::support_copy<pro::constraint_level::nothrow>
+    ::support_rtti
+    ::support_weak
+    ::build {};
+
+int main() {
+  pro::proxy<RttiAware> p1 = pro::make_proxy_shared<RttiAware>(123);
+  pro::weak_proxy<RttiAware> p2 = p1;
+  pro::proxy<RttiAware> p3 = p2.lock();
+  std::cout << std::boolalpha << p3.has_value() << "\n";  // Prints "true"
+  std::cout << proxy_cast<int>(*p3) << "\n";  // Prints "123"
+
+  p3.reset();
+  p1.reset();
+  p3 = p2.lock();
+  std::cout << std::boolalpha << p3.has_value() << "\n";  // Prints "false"
+}
diff --git a/samples/make_proxy_view.cpp b/samples/make_proxy_view.cpp
new file mode 100644
index 00000000..bd359577
--- /dev/null
+++ b/samples/make_proxy_view.cpp
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+// This file contains example code from make_proxy_view.md.
+
+#include <iostream>
+#include <map>
+#include <string>
+
+#include "proxy.h"
+
+PRO_DEF_MEM_DISPATCH(MemAt, at);
+
+struct ResourceDictionary : pro::facade_builder
+    ::add_convention<MemAt, std::string&(int index), const std::string&(int index) const>
+    ::build {};
+
+int main() {
+  std::map<int, std::string> dict;
+  dict[1] = "init";
+  pro::proxy_view<ResourceDictionary> pv = pro::make_proxy_view<ResourceDictionary>(dict);
+  static_assert(std::is_same_v<decltype(pv->at(1)), std::string&>, "Non-const overload");
+  static_assert(std::is_same_v<decltype(std::as_const(pv)->at(1)), const std::string&>, "Const overload");
+  std::cout << std::as_const(pv)->at(1) << "\n";  // Invokes the const overload and prints "init"
+  pv->at(1) = "modified";  // Invokes the non-const overload
+  std::cout << std::as_const(pv)->at(1) << "\n";  // Invokes the const overload and prints "modified"
+}
diff --git a/samples/proxiable_target.cpp b/samples/proxiable_target.cpp
new file mode 100644
index 00000000..0d89e7e7
--- /dev/null
+++ b/samples/proxiable_target.cpp
@@ -0,0 +1,15 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+// This file contains example code from proxiable_target.md.
+
+#include "proxy.h"
+
+struct Runnable : pro::facade_builder
+    ::add_convention<pro::operator_dispatch<"()">, void()>
+    ::build {};
+
+int main() {
+  auto fun = [] {};
+  static_assert(pro::proxiable_target<decltype(fun), Runnable>);
+  static_assert(!pro::proxiable_target<int, Runnable>);
+}
diff --git a/samples/weak_proxy.cpp b/samples/weak_proxy.cpp
new file mode 100644
index 00000000..632ee8d3
--- /dev/null
+++ b/samples/weak_proxy.cpp
@@ -0,0 +1,24 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+// This file contains example code from weak_proxy.md.
+
+#include <iostream>
+
+#include "proxy.h"
+
+struct Formattable : pro::facade_builder
+    ::support_format
+    ::build {};
+
+int main() {
+  std::shared_ptr<int> val = std::make_shared<int>(123);
+  pro::weak_proxy<Formattable> wp = std::weak_ptr{val};
+  pro::proxy<Formattable> p = wp.lock();
+  std::cout << std::boolalpha << p.has_value() << "\n";  // Prints "true"
+  std::cout << std::format("{}\n", *p);  // Prints "123"
+
+  p.reset();
+  val.reset();
+  p = wp.lock();
+  std::cout << p.has_value() << "\n";  // Prints "false"
+}
