proxy

Proxy’s Frequently Asked Questions

What is “Proxy” and how does it work?

“Proxy” is a single-header, 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.

“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 README, 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 single-header 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”:

  1. Update the compiler version to meet our minimum requirements for compilers.
  2. Define facade types that match the “base classes with virtual functions” (virtual base classes).
  3. Replace all the usage of virtual base classes with proxy from the API boundary.
  4. 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, when a construct of runtime abstraction has ownership of its context, “Proxy” usually has better performance than the inheritance-based approach in lifetime management. When performing an indirect call, “Proxy” usually generates similar code to a virtual function with equal performance. We have observed that when the concrete implementation and the abstraction appear in the same translation unit, a virtual function is more likely to be devirtualized in the generated code, but sometimes the compiler won’t do that trick for “Proxy”.

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_WEAK_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.