Proxy's Frequently Asked Questions
- What is "Proxy" and how does it work?
- Why is "Proxy" so popular?
- Who is "Proxy" for?
- Why should I use "Proxy"?
- How to learn "Proxy" effectively?
- How to integrate "Proxy" into my project?
- My existing project uses virtual functions. How should I migrate to "Proxy"?
- How is the performance compared to virtual functions?
- Why is "Proxy" based on pointer semantics rather than value semantics like
std::function
? - Why does "Proxy" define several macros instead of modern C++ facilities?
- What is the standardization progress of this library?
- What should I do if I found this library deficient in my scenario?
What is "Proxy" and how does it work?
"Proxy" is a header-only, cross-platform C++20 template library for modern runtime polymorphism based on pointer-semantics. Similar with C++ virtual functions, it generates indirect functions behind the scenes at compile-time but does not require inheritance. It also has GC-like behavior that allows different objects of the same proxy
type to have different lifetime models without requiring runtime GC overhead.
Why is "Proxy" so popular?
"Proxy" is built by engineers at Microsoft and initially deployed in the Windows operating system. For 40 years, the inheritance-based polymorphism paradigm has been the only scalable solution for runtime polymorphism in C++. However, a "virtual function" is no longer the optimal choice for runtime polymorphism today, and new languages with better paradigms, like traits in Rust, are emerging. "Proxy" is our latest and greatest solution for generic runtime polymorphism in C++. It is easy to integrate and makes C++ feel like a brand new language when dealing with runtime abstractions.
Who is "Proxy" for?
We encourage every C++ developer to use this library for production, including in embedded engineering scenarios. Before deciding to write any virtual function, consider whether using "Proxy" could simplify the architecture.
Why should I use "Proxy"?
While virtual functions have served well for decades, "Proxy" offers modern solutions that can lead to better performance, easier maintenance, and more flexible code design when it comes to runtime abstraction.
How to learn "Proxy" effectively?
The fundamental abstraction of "Proxy" is called "facade". It is recommended for beginners to start with the examples in the home page, try to understand the pattern of defining a facade
type, using a facade type to specify a proxy
type, and creating and using a proxy object at runtime. Don't hesitate to consult the specifications for more details about any facility in the library.
How to integrate "Proxy" into my project?
Since "Proxy" is a header-only library, you can simply navigate to the latest release, download the source code, and include "proxy.h" in your project. Make sure your compiler version meets the minimum requirements for compilers. If your project has already integrated with vcpkg or conan, just search for the keyword "proxy" and install it. Thanks to the community that helped port "Proxy" to these platforms!
My existing project uses virtual functions. How should I migrate to "Proxy"?
Follow the 4 steps below to upgrade an existing project from using virtual functions to "Proxy":
- Update the compiler version to meet our minimum requirements for compilers.
- Define
facade
types that match the "base classes with virtual functions" (virtual base classes). - Replace all the usage of virtual base classes with
proxy
from the API boundary. - Remove all the definitions and inheritance of virtual base classes.
How is the performance compared to virtual functions?
The design of "Proxy" follows the zero-overhead principle. With general compiler optimizations, "Proxy" is expected to generate high quality code in most scenarios that is not worse than an equivalent hand-written implementation with or without virtual functions. In practice, "Proxy" usually demonstrates better performance in indirect invocations than virtual functions, and in lifetime management than standard smart pointers or polymorphic wrappers. Please refer to our blog post for more details.
Why is "Proxy" based on pointer semantics rather than value semantics like std::function?
At the beginning, we explored the feasibility of designing a general-purpose polymorphic wrapper based on value semantics, just like std::function
and std::move_only_function
. It is technically feasible, but not as good as those languages with GC like C# or Java in terms of usability. We had a hard time refining the theory of OOP and finally realized that indirection is the nature of computer science, and decided to leverage the concept of pointer in C++ as the basis of "Proxy".
Why does "Proxy" define several macros instead of modern C++ facilities?
"Proxy" defines 4 macros: __msft_lib_proxy
, PRO_DEF_MEM_DISPATCH
, PRO_DEF_FREE_DISPATCH
, and PRO_DEF_FREE_AS_MEM_DISPATCH
. __msft_lib_proxy
is the feature test macro, following the existing practice in the C++20 standard. The other 3 macros are fundamental facilities to define a custom dispatch
type. These macros cannot be replaced by modern C++ facilities because there is no existing language feature prior to C++26 that allows generating a function with an arbitrary name. As a result, "Proxy" does not provide a default interface for modules as of now.
What is the standardization progress of this library?
Currently, there is an ongoing proposal being reviewed in the ISO C++ committee. The progress can be tracked here.
What should I do if I found this library deficient in my scenario?
Please search for your scenario in the existing issues first, and feel free to file an a new one on demand, following the Microsoft Open Source Code of Conduct.