| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Are you looking to simplify the lifetime management and maintenance of polymorphic objects in C++?
Do you want to write polymorphic code in C++ as easily as in GC languages like Java or C#, without sacrificing performance?
Have you tried other polymorphic programming libraries in C++ but found them deficient?
If so, this library is for you.
"Proxy" is a modern C++ library that helps you use polymorphism (a way to use different types of objects interchangeably) without needing inheritance.
"Proxy" was created by Microsoft engineers and incubated at Microsoft from 2018 to Feb 2026, and has been used in the Windows operating system since 2022. It is now maintained by the Next Gen C++ Foundation (ngcpp). This repository was ported from microsoft/proxy, where more historical releases can be found. For many years, using inheritance was the main way to achieve polymorphism in C++. However, new programming languages like Rust offer better ways to do this. We have improved our understanding of object-oriented programming and decided to use pointers in C++ as the foundation for "Proxy". Specifically, the "Proxy" library is designed to be:
Please refer to the Proxy's Frequently Asked Questions for more background, and refer to the specifications for more technical details.
"Proxy" is a header-only C++20 library. Make sure your compiler meets the minimum requirements, then pick one of three ways to use the library:
Let's get started with the following "Hello World" example (run):
#include <format>
#include <iostream>
#include <string>
#include <proxy/proxy.h>
struct Formattable : pro::facade_builder
::add_skill<pro::skills::format>
::build {};
int main() {
static std::string str = "Hello World";
pro::proxy<Formattable> p1 = &str;
std::cout << std::format("*p1 = {}\n", *p1); // Prints "*p1 = Hello World"
pro::proxy<Formattable> p2 = std::make_unique<int>(123);
std::cout << std::format("*p2 = {}\n", *p2); // Prints "*p2 = 123"
pro::proxy<Formattable> p3 = pro::make_proxy<Formattable>(3.14159);
std::cout << std::format("*p3 = {:.2f}\n", *p3); // Prints "*p3 = 3.14"
}Here is a step-by-step explanation:
Note: If you prefer the library to be consumed as a (C++20) module, refer to C++20 Modules support.
In the previous "Hello World" 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):
#include <iomanip>
#include <iostream>
#include <string>
#include <proxy/proxy.h>
struct Streamable : pro::facade_builder
::add_convention<pro::operator_dispatch<"<<", true>, std::ostream&(std::ostream& out) const>
::build {};
int main() {
static std::string str = "Hello World";
pro::proxy<Streamable> p1 = &str;
std::cout << "*p1 = " << *p1 << "\n"; // Prints "p1 = Hello World"
pro::proxy<Streamable> p2 = std::make_unique<int>(123);
std::cout << "*p2 = " << *p2 << "\n"; // Prints "p2 = 123"
pro::proxy<Streamable> p3 = pro::make_proxy<Streamable>(3.14159);
std::cout << "*p3 = " << std::fixed << std::setprecision(2) << *p3 << "\n"; // Prints "p3 = 3.14"
}Here is a step-by-step explanation:
#include <iomanip>: For std::setprecision.
#include <iostream>: For std::cout.
#include <string>: For std::string.
#include <proxy/proxy.h>: For the "Proxy" library.
struct Streamable : pro::facade_builder ... ::build {}: Defines a facade type Streamable. Specifically,
pro::proxy<Streamable> p1 = &str: Creates a proxy object from a raw pointer of std::string.
std::cout << *p1: It prints "Hello World" because the calling convention is defined in the facade Streamable, so it works as if by calling std::cout << str.
pro::proxy<Streamable> p2 = std::make_unique<int>(123): Creates a std::unique_ptr<int> and converts to a proxy.
std::cout << *p2: Prints "123" with no surprises.
pro::proxy<Streamable> p3 = pro::make_proxy<Streamable>(3.14): Creates a proxy from a double.
std::cout << std::fixed << std::setprecision(2) << *p3;: Prints "3.14" with no surprises.
In addition to the operator expressions demonstrated in the previous examples, the library supports almost all forms of expressions in C++ and can make them polymorphic. Specifically,
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):
#include <iostream>
#include <sstream>
#include <proxy/proxy.h>
PRO_DEF_MEM_DISPATCH(MemDraw, Draw);
PRO_DEF_MEM_DISPATCH(MemArea, Area);
struct Drawable : pro::facade_builder
::add_convention<MemDraw, void(std::ostream& output)>
::add_convention<MemArea, double() noexcept>
::support_copy<pro::constraint_level::nontrivial>
::build {};
class Rectangle {
public:
Rectangle(double width, double height) : width_(width), height_(height) {}
Rectangle(const Rectangle&) = default;
void Draw(std::ostream& out) const {
out << "{Rectangle: width = " << width_ << ", height = " << height_ << "}";
}
double Area() const noexcept { return width_ * height_; }
private:
double width_;
double height_;
};
std::string PrintDrawableToString(pro::proxy<Drawable> p) {
std::stringstream result;
result << "entity = ";
p->Draw(result);
result << ", area = " << p->Area();
return std::move(result).str();
}
int main() {
pro::proxy<Drawable> p = pro::make_proxy<Drawable, Rectangle>(3, 5);
std::string str = PrintDrawableToString(p);
std::cout << str << "\n"; // Prints "entity = {Rectangle: width = 3, height = 5}, area = 15"
}Here is a step-by-step explanation:
The "Proxy" library is a self-contained solution for runtime polymorphism in C++. There are many other capabilities documented in the specifications. In addition to the features mentioned above, here is a curated list of the most popular features based on user feedback:
| Family | Minimum version | Required flags |
|---|---|---|
| GCC | 13.1 | -std=c++20 |
| Clang | 16.0.0 | -std=c++20 |
| MSVC | 19.31 | /std:c++20 |
| NVIDIA HPC | 24.1 | -std=c++20 |
| Intel oneAPI | 2024.0 | -std=c++20 |
The snippets below show how to wire "Proxy" into a consuming project, preferring fetches directly from GitHub so you don't have to manage a local clone yourself.
Fetch via CPM (a thin wrapper over CMake's FetchContent_Declare):
CPMAddPackage(
NAME msft_proxy4
GIT_TAG 4.1.0
GIT_REPOSITORY https://github.com/ngcpp/proxy.git
)
target_link_libraries(main PRIVATE msft_proxy4::proxy)Or, if you already have a local clone, use add_subdirectory(path/to/proxy) instead of CPMAddPackage.
Place a wrap file at subprojects/proxy.wrap and Meson will fetch the source automatically:
[wrap-git]
url = https://github.com/ngcpp/proxy.git
revision = 4.1.0
[provide]
dependency_names = msft_proxy4Then in your meson.build:
msft_proxy4_dep = dependency('msft_proxy4')
executable('main', 'main.cpp', dependencies: msft_proxy4_dep)The library is not yet published to the Bazel Central Registry, so consumers point Bazel at the GitHub repository directly (or at a local clone).
With Bzlmod (Bazel 7+), add to your MODULE.bazel:
bazel_dep(name = "proxy", version = "4.1.0")
git_override(
module_name = "proxy",
remote = "https://github.com/ngcpp/proxy.git",
commit = "<commit SHA>", # `git_override` requires a SHA; tags are not accepted
)With legacy WORKSPACE mode (Bazel 5.1+ without Bzlmod), add to your WORKSPACE:
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
name = "proxy",
remote = "https://github.com/ngcpp/proxy.git",
tag = "4.1.0",
)
load("@proxy//:proxy_deps.bzl", "proxy_deps")
proxy_deps()Either way, add @proxy//:proxy to the deps of any cc_library or cc_binary target that needs it. If you'd rather work against a local clone, replace git_override with local_path_override(module_name = "proxy", path = "path/to/proxy").
Running the test suite (or contributing changes back) starts with cloning the repository:
git clone https://github.com/ngcpp/proxy.git cd proxy
Then drive the tests through any of the supported build systems:
cmake --preset default cmake --build --preset default -j ctest --preset default -j
meson setup build meson test -C build --suite ProxyTests
Testing requires Bazel 7+. The repository pins a specific Bazel version in .bazelversion to keep contributor builds reproducible. Install Bazelisk (invoked as bazel) and the pinned version is downloaded automatically.
bazel test //tests/...
This project welcomes contributions and suggestions. Some contributions may require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. If a CLA is required, the PR bot will provide instructions.
This project has adopted the Contributor Covenant Code of Conduct. For more information see the Contributor Covenant FAQ or contact ngcpp@outlook.com with any additional questions or comments.
| Back | FazBrowse Home | New Git URL |