diff --git a/.github/workflows/bvt-clang.yml b/.github/workflows/bvt-clang.yml index bbfe25e0..f690aeb6 100644 --- a/.github/workflows/bvt-clang.yml +++ b/.github/workflows/bvt-clang.yml @@ -15,20 +15,23 @@ jobs: - name: install clang run: | - sudo apt install -y clang-19 libc++-19-dev + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh 20 + sudo apt install libc++-20-dev - name: check compiler version run: | - clang++-19 --version + clang++-20 --version - - name: build and run test with clang 19 + - name: build and run test with clang 20 run: | - cmake -B build -DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19 -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_CXX_STANDARD=23 -DCMAKE_BUILD_TYPE=Release + cmake -B build -DCMAKE_C_COMPILER=clang-20 -DCMAKE_CXX_COMPILER=clang++-20 -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_CXX_STANDARD=23 -DCMAKE_BUILD_TYPE=Release cmake --build build -j ctest --test-dir build -j mkdir build/drop chmod +x tools/dump_build_env.sh - ./tools/dump_build_env.sh clang++-19 build/drop/env-info.json + ./tools/dump_build_env.sh clang++-20 build/drop/env-info.json - name: run benchmarks run: | diff --git a/.github/workflows/pipeline-release.yml b/.github/workflows/pipeline-release.yml index 89c5d8a4..3bbab50b 100644 --- a/.github/workflows/pipeline-release.yml +++ b/.github/workflows/pipeline-release.yml @@ -18,7 +18,7 @@ jobs: version=$(grep -oP 'msft_proxy\s+VERSION\s+\K[0-9]+\.[0-9]+\.[0-9]+' "$file") git tag "$version" git push origin "$version" - tar -czf "proxy-$version.tgz" "proxy.h" + tar -czf "proxy-$version.tgz" $(git ls-files 'include/**.h') echo "PRO_VER=$version" >> $GITHUB_OUTPUT shell: bash diff --git a/CMakeLists.txt b/CMakeLists.txt index 77dd586b..f615d7e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,17 +1,41 @@ cmake_minimum_required(VERSION 3.10) -project(msft_proxy VERSION 3.3.0 LANGUAGES CXX) +project(msft_proxy VERSION 3.4.0 LANGUAGES CXX) add_library(msft_proxy INTERFACE) + +# Do not enable building tests if proxy is consumed as +# subdirectory (e.g. by CMake FetchContent_Declare). +if(PROJECT_IS_TOP_LEVEL) + option(BUILD_TESTING "Build tests" ON) +else() + option(BUILD_TESTING "Build tests" OFF) +endif() + +target_sources(msft_proxy + INTERFACE + FILE_SET public_headers + TYPE HEADERS + BASE_DIRS include + FILES + include/proxy/proxy.h + include/proxy/v3/proxy.h +) + target_compile_features(msft_proxy INTERFACE cxx_std_20) -target_include_directories(msft_proxy INTERFACE $ +target_include_directories(msft_proxy INTERFACE $ $) +set(proxy_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include") +if(NOT PROJECT_IS_TOP_LEVEL) + set(proxy_INCLUDE_DIR "${proxy_INCLUDE_DIR}" PARENT_SCOPE) +endif() + # install and export the project. project name - proxy include(GNUInstallDirs) install(TARGETS msft_proxy - EXPORT proxyConfig) -install(FILES proxy.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/proxy) + EXPORT proxyConfig + FILE_SET public_headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) install(EXPORT proxyConfig DESTINATION ${CMAKE_INSTALL_DATADIR}/proxy) export(TARGETS msft_proxy FILE proxyConfig.cmake) include(CMakePackageConfigHelpers) @@ -22,9 +46,9 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/proxyConfigVersion.cmake DESTINATION ${CMAKE_INSTALL_DATADIR}/proxy) # build tests if BUILD_TESTING is ON -include(CTest) if (BUILD_TESTING) + include(CTest) add_subdirectory(tests) add_subdirectory(benchmarks) - add_subdirectory(samples) + add_subdirectory(docs) endif() diff --git a/README.md b/README.md index 80fb1052..5ebbbaca 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,20 @@ Please refer to the [Proxy's Frequently Asked Questions](https://microsoft.githu ## Quick Start -"Proxy" is a header-only C++20 library. To use the library, make sure your compiler meets the [minimum requirements](#compiler-req) and just include the header file [proxy.h](https://github.com/microsoft/proxy/blob/main/proxy.h) in your source code. Alternatively, you can install the library via [vcpkg](https://learn.microsoft.com/en-us/vcpkg/get_started/overview) or [conan](https://conan.io/), by searching for "proxy" (see [vcpkg.io](https://vcpkg.io/en/package/proxy) and [conan.io](https://conan.io/center/recipes/proxy)). +"Proxy" is a header-only C++20 library. To use the library, make sure your compiler meets the [minimum requirements](#compiler-req) and just put the [proxy](https://github.com/microsoft/proxy/tree/main/include/proxy) directory in your project's include directory. Alternatively, you can install the library via: + +- [vcpkg](https://learn.microsoft.com/en-us/vcpkg/get_started/overview): [proxy port on vcpkg.io](https://vcpkg.io/en/package/proxy) +- [conan](https://conan.io/): [proxy recipe on conan.io](https://conan.io/center/recipes/proxy) +- [CPM](https://github.com/cpm-cmake/CPM.cmake) / CMake [FetchContent_Declare](https://cmake.org/cmake/help/latest/module/FetchContent.html): + + ```cmake + CPMAddPackage( + NAME proxy + GIT_TAG 3.4.0 # or above + GIT_REPOSITORY https://github.com/microsoft/proxy.git + ) + target_link_libraries(main PRIVATE msft_proxy) + ``` ### Hello World @@ -38,7 +51,7 @@ Let's get started with the following "Hello World" example ([run](https://godbol #include #include -#include "proxy.h" +#include struct Formattable : pro::facade_builder ::support_format @@ -62,7 +75,7 @@ Here is a step-by-step explanation: - `#include `: For [`std::format`](https://en.cppreference.com/w/cpp/utility/format/format). - `#include `: For [`std::cout`](https://en.cppreference.com/w/cpp/io/cout). - `#include `: For [`std::string`](https://en.cppreference.com/w/cpp/string/basic_string). -- `#include "proxy.h"`: For the "Proxy" library. Most of the facilities of the library are defined in namespace `pro`. If the library is consumed via [vcpkg](https://learn.microsoft.com/en-us/vcpkg/get_started/overview) or [conan](https://conan.io/), this line should be changed into `#include `. +- `#include `: For the "Proxy" library. Most of the facilities of the library are defined in namespace `pro`. - `struct Formattable : pro::facade_builder ... ::build {}`: Defines a facade type `Formattable`. The term "facade", formally defined as the [*ProFacade* requirements](https://microsoft.github.io/proxy/docs/ProFacade.html), is how the "Proxy" library models runtime abstraction. Specifically, - [`pro::facade_builder`](https://microsoft.github.io/proxy/docs/basic_facade_builder.html): Provides capability to build a facade type at compile-time. - [`support_format`](https://microsoft.github.io/proxy/docs/basic_facade_builder/support_format.html): Specifies the capability of formatting (via [standard formatting functions](https://en.cppreference.com/w/cpp/utility/format)). @@ -87,7 +100,7 @@ In the previous "Hello Word" example, we demonstrated how `proxy` could manage d #include #include -#include "proxy.h" +#include struct Streamable : pro::facade_builder ::add_convention, std::ostream&(std::ostream& out) const> @@ -108,10 +121,10 @@ int main() { Here is a step-by-step explanation: -- `#include `: For [`std::setprecision`](https://en.cppreference.com/w/cpp/io/manip/setprecision). +- `#include `: For [`std::setprecision`](https://en.cppreference.com/w/cpp/io/manip/setprecision). - `#include `: For [`std::cout`](https://en.cppreference.com/w/cpp/io/cout). - `#include `: For [`std::string`](https://en.cppreference.com/w/cpp/string/basic_string). -- `#include "proxy.h"`: For the "Proxy" library. +- `#include `: For the "Proxy" library. - `struct Streamable : pro::facade_builder ... ::build {}`: Defines a facade type `Streamable`. Specifically, - [`pro::facade_builder`](https://microsoft.github.io/proxy/docs/basic_facade_builder.html): Gets prepared to build another facade. - [`add_convention`](https://microsoft.github.io/proxy/docs/basic_facade_builder/add_convention.html): Adds a generalized "calling convention", defined by a "dispatch" and several "overloads", to the build context. @@ -142,7 +155,7 @@ Note that some facilities are provided as macro, because C++ templates today do #include #include -#include "proxy.h" +#include PRO_DEF_MEM_DISPATCH(MemDraw, Draw); PRO_DEF_MEM_DISPATCH(MemArea, Area); @@ -187,7 +200,7 @@ Here is a step-by-step explanation: - `#include `: For [`std::cout`](https://en.cppreference.com/w/cpp/io/cout). - `#include `: For [`std::stringstream`](https://en.cppreference.com/w/cpp/io/basic_stringstream). -- `#include "proxy.h"`: For the "Proxy" library. +- `#include `: For the "Proxy" library. - [`PRO_DEF_MEM_DISPATCH`](https://microsoft.github.io/proxy/docs/PRO_DEF_MEM_DISPATCH.html)`(MemDraw, Draw)`: Defines a dispatch type `MemDraw` for expressions of calling member function `Draw`. - [`PRO_DEF_MEM_DISPATCH`](https://microsoft.github.io/proxy/docs/PRO_DEF_MEM_DISPATCH.html)`(MemArea, Area)`: Defines a dispatch type `MemArea` for expressions of calling member function `Area`. - `struct Drawable : pro::facade_builder ... ::build {}`: Defines a facade type `Drawable`. Specifically, diff --git a/benchmarks/proxy_invocation_benchmark_context.h b/benchmarks/proxy_invocation_benchmark_context.h index 9477b2a5..752edf5b 100644 --- a/benchmarks/proxy_invocation_benchmark_context.h +++ b/benchmarks/proxy_invocation_benchmark_context.h @@ -4,7 +4,7 @@ #include #include -#include "proxy.h" +#include PRO_DEF_MEM_DISPATCH(MemFun, Fun); diff --git a/benchmarks/proxy_management_benchmark.cpp b/benchmarks/proxy_management_benchmark.cpp index ce7b2501..273576a9 100644 --- a/benchmarks/proxy_management_benchmark.cpp +++ b/benchmarks/proxy_management_benchmark.cpp @@ -9,7 +9,7 @@ #include -#include "proxy.h" +#include namespace { diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt new file mode 100644 index 00000000..875f42c3 --- /dev/null +++ b/docs/CMakeLists.txt @@ -0,0 +1,28 @@ +project(msft_proxy_docs) + +find_package(Python3 REQUIRED COMPONENTS Interpreter) + +file(GLOB_RECURSE DOC_FILES "*.md") +set(EXTRACTION_SCRIPT ${CMAKE_SOURCE_DIR}/tools/extract_example_code_from_docs.py) +set(EXAMPLES_DIR ${CMAKE_BINARY_DIR}/examples_from_docs) +file(MAKE_DIRECTORY "${EXAMPLES_DIR}") +execute_process( + COMMAND ${Python3_EXECUTABLE} ${EXTRACTION_SCRIPT} ${CMAKE_CURRENT_SOURCE_DIR} ${EXAMPLES_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND_ERROR_IS_FATAL ANY +) + +file(GLOB EXAMPLE_SOURCES "${EXAMPLES_DIR}/*.cpp") +set_source_files_properties(${EXAMPLE_SOURCES} PROPERTIES GENERATED TRUE) +foreach(SOURCE ${EXAMPLE_SOURCES}) + get_filename_component(EXECUTABLE_NAME ${SOURCE} NAME_WE) + add_executable(${EXECUTABLE_NAME} ${SOURCE}) + target_link_libraries(${EXECUTABLE_NAME} PRIVATE msft_proxy) + if (MSVC) + target_compile_options(${EXECUTABLE_NAME} PRIVATE /W4) + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + target_compile_options(${EXECUTABLE_NAME} PRIVATE -Wall -Wextra -Wpedantic -Wno-c++2b-extensions) + else() + target_compile_options(${EXECUTABLE_NAME} PRIVATE -Wall -Wextra -Wpedantic) + endif() +endforeach() diff --git a/docs/PRO_DEF_FREE_AS_MEM_DISPATCH.md b/docs/PRO_DEF_FREE_AS_MEM_DISPATCH.md index d2fb494f..e7a0a0d6 100644 --- a/docs/PRO_DEF_FREE_AS_MEM_DISPATCH.md +++ b/docs/PRO_DEF_FREE_AS_MEM_DISPATCH.md @@ -45,13 +45,15 @@ struct dispatch_name { } ``` +When headers from different major versions of the Proxy library can appear in the same translation unit (for example, Proxy 3 and Proxy 4), use the major-qualified form `PRO_DEF_FREE_AS_MEM_DISPATCH` (e.g., `PRO3_DEF_FREE_AS_MEM_DISPATCH`). + ## Example ```cpp #include #include -#include "proxy.h" +#include PRO_DEF_FREE_AS_MEM_DISPATCH(FreeToString, std::to_string, ToString); diff --git a/docs/PRO_DEF_FREE_DISPATCH.md b/docs/PRO_DEF_FREE_DISPATCH.md index c65ecc81..ac9b5bed 100644 --- a/docs/PRO_DEF_FREE_DISPATCH.md +++ b/docs/PRO_DEF_FREE_DISPATCH.md @@ -43,13 +43,15 @@ struct dispatch_name { } ``` +When headers from different major versions of the Proxy library can appear in the same translation unit (for example, Proxy 3 and Proxy 4), use the major-qualified form `PRO_DEF_FREE_DISPATCH` (e.g., `PRO3_DEF_FREE_DISPATCH`). + ## Example ```cpp #include #include -#include "proxy.h" +#include PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); diff --git a/docs/PRO_DEF_MEM_DISPATCH.md b/docs/PRO_DEF_MEM_DISPATCH.md index 55f3641b..8007288a 100644 --- a/docs/PRO_DEF_MEM_DISPATCH.md +++ b/docs/PRO_DEF_MEM_DISPATCH.md @@ -45,6 +45,8 @@ struct dispatch_name { } ``` +When headers from different major versions of the Proxy library can appear in the same translation unit (for example, Proxy 3 and Proxy 4), use the major-qualified form `PRO_DEF_MEM_DISPATCH` (e.g., `PRO3_DEF_MEM_DISPATCH`). + ## Example ```cpp @@ -52,7 +54,7 @@ struct dispatch_name { #include #include -#include "proxy.h" +#include PRO_DEF_MEM_DISPATCH(MemAt, at); diff --git a/docs/PRO_DEF_WEAK_DISPATCH.md b/docs/PRO_DEF_WEAK_DISPATCH.md index 09714915..7cd29167 100644 --- a/docs/PRO_DEF_WEAK_DISPATCH.md +++ b/docs/PRO_DEF_WEAK_DISPATCH.md @@ -39,7 +39,7 @@ In [Java](https://docs.oracle.com/javase/specs/jls/se23/html/jls-9.html#jls-9.4- #include #include -#include "proxy.h" +#include struct NotImplemented { explicit NotImplemented(auto&&...) { throw std::runtime_error{ "Not implemented!" }; } diff --git a/docs/access_proxy.md b/docs/access_proxy.md index 0d1bfe6d..0a39823c 100644 --- a/docs/access_proxy.md +++ b/docs/access_proxy.md @@ -33,7 +33,7 @@ Similar to [`proxy_invoke`](proxy_invoke.md), this function can be used to imple #include #include -#include "proxy.h" +#include PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); diff --git a/docs/allocate_proxy.md b/docs/allocate_proxy.md index cb9a911d..1e2f70ec 100644 --- a/docs/allocate_proxy.md +++ b/docs/allocate_proxy.md @@ -41,7 +41,7 @@ The implementation of `allocated-ptr` may vary depending on the definition of `F ```cpp #include -#include "proxy.h" +#include // By default, the maximum pointer size defined by pro::facade_builder // is 2 * sizeof(void*). This value can be overridden by `restrict_layout`. diff --git a/docs/allocate_proxy_shared.md b/docs/allocate_proxy_shared.md index 14d6006f..c1e2ccf2 100644 --- a/docs/allocate_proxy_shared.md +++ b/docs/allocate_proxy_shared.md @@ -42,7 +42,7 @@ The implementation of `strong-compact-ptr` may vary depending on the definition #include #include -#include "proxy.h" +#include struct RttiAware : pro::facade_builder ::support_copy diff --git a/docs/basic_facade_builder.md b/docs/basic_facade_builder.md index 39e5107b..b231b557 100644 --- a/docs/basic_facade_builder.md +++ b/docs/basic_facade_builder.md @@ -115,7 +115,7 @@ struct CopyableCallable : pro::facade_builder ```cpp #include -#include "proxy.h" +#include template struct MovableCallable : pro::facade_builder diff --git a/docs/basic_facade_builder/add_convention.md b/docs/basic_facade_builder/add_convention.md index 165ddc1a..aba5f395 100644 --- a/docs/basic_facade_builder/add_convention.md +++ b/docs/basic_facade_builder/add_convention.md @@ -38,7 +38,7 @@ Adding duplicated combinations of some dispatch type and overload type is well-d #include #include -#include "proxy.h" +#include PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); diff --git a/docs/basic_facade_builder/add_facade.md b/docs/basic_facade_builder/add_facade.md index 0fa12812..6a843bc1 100644 --- a/docs/basic_facade_builder/add_facade.md +++ b/docs/basic_facade_builder/add_facade.md @@ -17,7 +17,7 @@ Adding a facade type that contains duplicated convention or reflection types alr #include #include -#include "proxy.h" +#include PRO_DEF_MEM_DISPATCH(MemSize, size); PRO_DEF_MEM_DISPATCH(MemAt, at); diff --git a/docs/basic_facade_builder/add_reflection.md b/docs/basic_facade_builder/add_reflection.md index 4edc03a8..7a5e99d9 100644 --- a/docs/basic_facade_builder/add_reflection.md +++ b/docs/basic_facade_builder/add_reflection.md @@ -35,7 +35,7 @@ Adding duplicate reflection types is well-defined, whether done directly via `ad #include #include -#include "proxy.h" +#include struct LayoutReflector { public: diff --git a/docs/basic_facade_builder/build.md b/docs/basic_facade_builder/build.md index d365fa0b..75ab53fa 100644 --- a/docs/basic_facade_builder/build.md +++ b/docs/basic_facade_builder/build.md @@ -57,7 +57,7 @@ The default values of the fields of [`proxiable_ptr_constraints`](../proxiable_p ```cpp #include -#include "proxy.h" +#include struct DefaultBase : pro::facade_builder ::build {}; diff --git a/docs/basic_facade_builder/restrict_layout.md b/docs/basic_facade_builder/restrict_layout.md index 3d78fb61..c291d368 100644 --- a/docs/basic_facade_builder/restrict_layout.md +++ b/docs/basic_facade_builder/restrict_layout.md @@ -18,7 +18,7 @@ If no layout restriction is applied before specifying [`build`](build.md), the d #include #include -#include "proxy.h" +#include struct DefaultFacade : pro::facade_builder::build {}; diff --git a/docs/basic_facade_builder/support_copy.md b/docs/basic_facade_builder/support_copy.md index 79a7d508..986a2832 100644 --- a/docs/basic_facade_builder/support_copy.md +++ b/docs/basic_facade_builder/support_copy.md @@ -16,7 +16,7 @@ If no copyability support is applied before specifying [`build`](build.md), the ```cpp #include -#include "proxy.h" +#include struct Movable : pro::facade_builder::build {}; diff --git a/docs/basic_facade_builder/support_destruction.md b/docs/basic_facade_builder/support_destruction.md index 66f705e1..e7387af6 100644 --- a/docs/basic_facade_builder/support_destruction.md +++ b/docs/basic_facade_builder/support_destruction.md @@ -16,7 +16,7 @@ If no destructibility support is applied before specifying [`build`](build.md), ```cpp #include -#include "proxy.h" +#include struct Movable : pro::facade_builder::build {}; diff --git a/docs/basic_facade_builder/support_format.md b/docs/basic_facade_builder/support_format.md index 3866fcfa..a44a5691 100644 --- a/docs/basic_facade_builder/support_format.md +++ b/docs/basic_facade_builder/support_format.md @@ -16,7 +16,7 @@ The member types `support_format` and `support_wformat` of `basic_facade_builder #include #include -#include "proxy.h" +#include struct Formattable : pro::facade_builder ::support_format diff --git a/docs/basic_facade_builder/support_relocation.md b/docs/basic_facade_builder/support_relocation.md index a59cfade..f5f5b7af 100644 --- a/docs/basic_facade_builder/support_relocation.md +++ b/docs/basic_facade_builder/support_relocation.md @@ -16,7 +16,7 @@ If no relocatability support is applied before specifying [`build`](build.md), t ```cpp #include -#include "proxy.h" +#include struct Movable : pro::facade_builder::build {}; diff --git a/docs/basic_facade_builder/support_rtti.md b/docs/basic_facade_builder/support_rtti.md index f6fdc917..92a7bf99 100644 --- a/docs/basic_facade_builder/support_rtti.md +++ b/docs/basic_facade_builder/support_rtti.md @@ -22,7 +22,7 @@ The member types `support_rtti`, `support_indirect_rtti` and `support_direct_rtt ```cpp #include -#include "proxy.h" +#include struct RttiAware : pro::facade_builder ::support_rtti diff --git a/docs/basic_facade_builder/support_rtti/proxy_cast.md b/docs/basic_facade_builder/support_rtti/proxy_cast.md index 8922cb57..9419bbab 100644 --- a/docs/basic_facade_builder/support_rtti/proxy_cast.md +++ b/docs/basic_facade_builder/support_rtti/proxy_cast.md @@ -61,7 +61,7 @@ These functions are not visible to ordinary [unqualified](https://en.cppreferenc ```cpp #include -#include "proxy.h" +#include struct RttiAware : pro::facade_builder ::support_rtti diff --git a/docs/basic_facade_builder/support_rtti/proxy_typeid.md b/docs/basic_facade_builder/support_rtti/proxy_typeid.md index d5fae268..9d8e8531 100644 --- a/docs/basic_facade_builder/support_rtti/proxy_typeid.md +++ b/docs/basic_facade_builder/support_rtti/proxy_typeid.md @@ -20,7 +20,7 @@ These functions are not visible to ordinary [unqualified](https://en.cppreferenc ```cpp #include -#include "proxy.h" +#include struct RttiAware : pro::facade_builder ::support_rtti diff --git a/docs/basic_facade_builder/support_view.md b/docs/basic_facade_builder/support_view.md index ca6324bb..900d0d93 100644 --- a/docs/basic_facade_builder/support_view.md +++ b/docs/basic_facade_builder/support_view.md @@ -17,7 +17,7 @@ Let `p` be a value of type `proxy`, `ptr` be the contained value of `p` (if a ```cpp #include -#include "proxy.h" +#include struct RttiAware : pro::facade_builder ::support_rtti diff --git a/docs/basic_facade_builder/support_weak.md b/docs/basic_facade_builder/support_weak.md index 81a3378c..3ea1bbd1 100644 --- a/docs/basic_facade_builder/support_weak.md +++ b/docs/basic_facade_builder/support_weak.md @@ -17,7 +17,7 @@ Let `p` be a value of type `proxy`, `ptr` of type `P` be the contained value ```cpp #include -#include "proxy.h" +#include struct Formattable : pro::facade_builder ::support_format diff --git a/docs/explicit_conversion_dispatch.md b/docs/explicit_conversion_dispatch.md index 44072034..ecb159de 100644 --- a/docs/explicit_conversion_dispatch.md +++ b/docs/explicit_conversion_dispatch.md @@ -26,7 +26,7 @@ Class `explicit_conversion_dispatch` models a [dispatch](ProDispatch.md) type fo ```cpp #include -#include "proxy.h" +#include struct IntConvertible : pro::facade_builder ::add_convention diff --git a/docs/facade_aware_overload_t.md b/docs/facade_aware_overload_t.md index 67865984..97f132eb 100644 --- a/docs/facade_aware_overload_t.md +++ b/docs/facade_aware_overload_t.md @@ -16,7 +16,7 @@ Class template `facade_aware_overload_t` specifies a facade-aware overload te ```cpp #include -#include "proxy.h" +#include template using BinaryOverload = pro::proxy(const pro::proxy_indirect_accessor& rhs) const; diff --git a/docs/faq.md b/docs/faq.md index 64315796..9d7fcce5 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -11,6 +11,7 @@ - [**Why is "Proxy" based on pointer semantics rather than value semantics like `std::function`?**](#why-pointer) - [**Why does "Proxy" define several macros instead of modern C++ facilities?**](#why-macros) - [**What is the standardization progress of this library?**](#standardization) +- [**How do I upgrade "Proxy" in a large codebase?**](#how-upgrade) - [**What should I do if I found this library deficient in my scenario?**](#help-needed) ### What is "Proxy" and how does it work? @@ -62,6 +63,26 @@ At the beginning, we explored the feasibility of designing a general-purpose pol Currently, there is [an ongoing proposal](https://wg21.link/p3086) being reviewed in the ISO C++ committee. The progress can be tracked [here](https://github.com/cplusplus/papers/issues/1741). +### How do I upgrade "Proxy" in a large codebase? + +Upgrading a small component is usually straightforward, but migrating a monorepo or multi-module product can be challenging. Follow the guidelines below: + +1. **Minor or patch upgrades (e.g. 3.3.0 → 3.4.0)** + All 3.x.y releases preserve API/ABI compatibility, so different parts of the program may safely depend on different 3.x.y versions. No special action is required. + +2. **Major upgrades (e.g. 3.4.0 → 4.0.0)** + - If your current version is *earlier* than 3.4.0, migrate to 3.4.0 first. + - Starting with 3.4.0, each major release is placed in a versioned inline namespace (`pro::v3`, `pro::v4`, …).  When a translation unit sees multiple majors, qualify the namespace explicitly: + ```cpp + pro::v3::foo();   // Proxy 3 API + pro::v4::foo();   // Proxy 4 API + ``` + The newest release re-exports its namespace as the inline (default) namespace, so unqualified calls (`pro::foo()`) resolve to the latest version once the migration is complete. + - The macros also have major-qualified aliases, e.g. [`PRO3_DEF_MEM_DISPATCH`](PRO_DEF_MEM_DISPATCH.md). Use these forms whenever headers from multiple majors are included in the same translation unit. + - Upgrade subsystems incrementally, module-by-module or DLL-by-DLL. When every target depends only on the new major, drop the old include path and remove the previous version from your build. + +These rules let old and new code coexist during the transition while keeping ODR violations at bay. + ### 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](https://opensource.microsoft.com/codeofconduct/). diff --git a/docs/implicit_conversion_dispatch.md b/docs/implicit_conversion_dispatch.md index ae57ffc9..dbaa2a01 100644 --- a/docs/implicit_conversion_dispatch.md +++ b/docs/implicit_conversion_dispatch.md @@ -24,7 +24,7 @@ Class `implicit_conversion_dispatch` models a [dispatch](ProDispatch.md) type fo ```cpp #include -#include "proxy.h" +#include struct Runnable : pro::facade_builder ::add_convention, void()> diff --git a/docs/inplace_proxiable_target.md b/docs/inplace_proxiable_target.md index 22e182ed..a6cfb8db 100644 --- a/docs/inplace_proxiable_target.md +++ b/docs/inplace_proxiable_target.md @@ -12,7 +12,7 @@ See [`make_proxy_inplace`](make_proxy_inplace.md) for the definition of the expo ```cpp #include -#include "proxy.h" +#include // By default, the maximum pointer size defined by pro::facade_builder // is 2 * sizeof(void*). This value can be overridden by `restrict_layout`. diff --git a/docs/make_proxy.md b/docs/make_proxy.md index 07482bd1..da61ac8c 100644 --- a/docs/make_proxy.md +++ b/docs/make_proxy.md @@ -50,7 +50,7 @@ Throws any exception thrown by allocation and the constructor of `T`. #include #include -#include "proxy.h" +#include struct Printable : pro::facade_builder ::add_convention, std::ostream&(std::ostream&) const> diff --git a/docs/make_proxy_inplace.md b/docs/make_proxy_inplace.md index c2143c5c..b622e9b6 100644 --- a/docs/make_proxy_inplace.md +++ b/docs/make_proxy_inplace.md @@ -44,7 +44,7 @@ Throws any exception thrown by the constructor of `T`. ```cpp #include -#include "proxy.h" +#include // By default, the maximum pointer size defined by pro::facade_builder // is 2 * sizeof(void*). This value can be overridden by `restrict_layout`. diff --git a/docs/make_proxy_shared.md b/docs/make_proxy_shared.md index c6a5f7d0..09cf6689 100644 --- a/docs/make_proxy_shared.md +++ b/docs/make_proxy_shared.md @@ -35,7 +35,7 @@ Throws any exception thrown by allocation and the constructor of `T`. ```cpp #include -#include "proxy.h" +#include struct RttiAware : pro::facade_builder ::support_copy diff --git a/docs/make_proxy_view.md b/docs/make_proxy_view.md index 9316049a..b18b9d26 100644 --- a/docs/make_proxy_view.md +++ b/docs/make_proxy_view.md @@ -20,7 +20,7 @@ The constructed `proxy_view` object. #include #include -#include "proxy.h" +#include PRO_DEF_MEM_DISPATCH(MemAt, at); diff --git a/docs/msft_lib_proxy.md b/docs/msft_lib_proxy.md index 9b8836c3..9df4e9f5 100644 --- a/docs/msft_lib_proxy.md +++ b/docs/msft_lib_proxy.md @@ -4,10 +4,11 @@ #define __msft_lib_proxy /* see below */ ``` -Similar to the standard [feature test macros](https://en.cppreference.com/w/cpp/feature_test), library "Proxy" has defined a feature test macro since 3.0.0. The table below maps each release version number to the corresponding value of `__msft_lib_proxy`. +Starting with 3.0.0, Proxy ships a feature-test macro that encodes the library version. When headers from different major versions of the Proxy library can appear in the same translation unit (for example, Proxy 3 and Proxy 4), use the major-qualified form `__msft_lib_proxy` (e.g., `__msft_lib_proxy3`). | Version | Value of `__msft_lib_proxy` | | ------- | --------------------------- | +| 3.4.0 | `202505L` | | 3.3.0 | `202503L` | | 3.2.1 | `202502L` | | 3.2.0 | `202501L` | @@ -19,7 +20,7 @@ Similar to the standard [feature test macros](https://en.cppreference.com/w/cpp/ ```cpp #include -#include "proxy.h" +#include int main() { #if defined(__msft_lib_proxy) && __msft_lib_proxy >= 202408L diff --git a/docs/operator_dispatch.md b/docs/operator_dispatch.md index 52114d4e..1db33def 100644 --- a/docs/operator_dispatch.md +++ b/docs/operator_dispatch.md @@ -120,7 +120,7 @@ Let `self` be the operand of [`proxy`](proxy.md), and `other` and `others...` be #include #include -#include "proxy.h" +#include struct Number : pro::facade_builder ::add_convention, void(int)> diff --git a/docs/proxiable.md b/docs/proxiable.md index 70bcb12f..33237d0b 100644 --- a/docs/proxiable.md +++ b/docs/proxiable.md @@ -13,7 +13,7 @@ The concept `proxiable` specifies that [`proxy`](proxy.md) can potentia #include #include -#include "proxy.h" +#include PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); diff --git a/docs/proxiable_target.md b/docs/proxiable_target.md index c077c28a..444b7adc 100644 --- a/docs/proxiable_target.md +++ b/docs/proxiable_target.md @@ -10,7 +10,7 @@ See [`make_proxy_view`](make_proxy_view.md) for the definition of the exposition ## Example ```cpp -#include "proxy.h" +#include struct Runnable : pro::facade_builder ::add_convention, void()> diff --git a/docs/proxy.md b/docs/proxy.md index 68559a16..4ebf400c 100644 --- a/docs/proxy.md +++ b/docs/proxy.md @@ -48,7 +48,7 @@ Another major difference is that `proxy` is open to abstractions. Unlike `std::f #include #include -#include "proxy.h" +#include PRO_DEF_MEM_DISPATCH(MemAt, at); diff --git a/docs/proxy/constructor.md b/docs/proxy/constructor.md index d3f1df2c..523d4f53 100644 --- a/docs/proxy/constructor.md +++ b/docs/proxy/constructor.md @@ -85,7 +85,7 @@ The constructors of `proxy` are similar to but have certain differences from #include #include -#include "proxy.h" +#include PRO_DEF_MEM_DISPATCH(MemSize, size); PRO_DEF_MEM_DISPATCH(MemClear, clear); diff --git a/docs/proxy/destructor.md b/docs/proxy/destructor.md index 2e85df2e..08066a3a 100644 --- a/docs/proxy/destructor.md +++ b/docs/proxy/destructor.md @@ -15,7 +15,7 @@ Destroys the `proxy` object. If the `proxy` contains a value, the contained valu ```cpp #include -#include "proxy.h" +#include struct AnyMovable : pro::facade_builder::build {}; diff --git a/docs/proxy/emplace.md b/docs/proxy/emplace.md index 3225528e..ef98f205 100644 --- a/docs/proxy/emplace.md +++ b/docs/proxy/emplace.md @@ -47,7 +47,7 @@ Similar to [`std::any::emplace`](https://en.cppreference.com/w/cpp/utility/any/e #include #include -#include "proxy.h" +#include struct AnyCopyable : pro::facade_builder ::support_copy diff --git a/docs/proxy/friend_operator_equality.md b/docs/proxy/friend_operator_equality.md index 0e281abc..e4b7e0a5 100644 --- a/docs/proxy/friend_operator_equality.md +++ b/docs/proxy/friend_operator_equality.md @@ -19,7 +19,7 @@ The `!=` operator is [synthesized](https://en.cppreference.com/w/cpp/language/de ```cpp #include -#include "proxy.h" +#include struct AnyMovable : pro::facade_builder::build {}; diff --git a/docs/proxy/friend_swap.md b/docs/proxy/friend_swap.md index 637dbcc3..ee5c1e16 100644 --- a/docs/proxy/friend_swap.md +++ b/docs/proxy/friend_swap.md @@ -15,7 +15,7 @@ This function is not visible to ordinary [unqualified](https://en.cppreference.c #include #include -#include "proxy.h" +#include PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); diff --git a/docs/proxy/indirection.md b/docs/proxy/indirection.md index c2160557..fb6ae42d 100644 --- a/docs/proxy/indirection.md +++ b/docs/proxy/indirection.md @@ -38,7 +38,7 @@ These operators do not check whether the `proxy` contains a value. To check whet #include #include -#include "proxy.h" +#include PRO_DEF_MEM_DISPATCH(MemSize, size); diff --git a/docs/proxy/operator_bool.md b/docs/proxy/operator_bool.md index d5409afb..b7507c04 100644 --- a/docs/proxy/operator_bool.md +++ b/docs/proxy/operator_bool.md @@ -16,7 +16,7 @@ Checks whether `*this` contains a value. ```cpp #include -#include "proxy.h" +#include struct AnyMovable : pro::facade_builder::build {}; diff --git a/docs/proxy/reset.md b/docs/proxy/reset.md index fedd8af7..0d867832 100644 --- a/docs/proxy/reset.md +++ b/docs/proxy/reset.md @@ -13,7 +13,7 @@ Destroys the contained value if it exists. After the call, `*this` does not cont ```cpp #include -#include "proxy.h" +#include struct AnyMovable : pro::facade_builder::build {}; diff --git a/docs/proxy_invoke.md b/docs/proxy_invoke.md index 61ea063e..0ae4ba11 100644 --- a/docs/proxy_invoke.md +++ b/docs/proxy_invoke.md @@ -45,7 +45,7 @@ It is generally not recommended to call `proxy_invoke` directly. Using an [`acce #include #include -#include "proxy.h" +#include PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); diff --git a/docs/proxy_reflect.md b/docs/proxy_reflect.md index 6e08849f..a1ae872c 100644 --- a/docs/proxy_reflect.md +++ b/docs/proxy_reflect.md @@ -20,7 +20,7 @@ This function is useful when only metadata deduced from a type is needed. While #include #include -#include "proxy.h" +#include class CopyabilityReflector { public: diff --git a/docs/proxy_view.md b/docs/proxy_view.md index be7e1292..a1dad95a 100644 --- a/docs/proxy_view.md +++ b/docs/proxy_view.md @@ -28,7 +28,7 @@ Class template `observer_facade` is a [facade](facade.md) type for observer poin ```cpp #include -#include "proxy.h" +#include template struct FMap : pro::facade_builder diff --git a/docs/specifications.md b/docs/specifications.md index bb7724f7..5a4509fb 100644 --- a/docs/specifications.md +++ b/docs/specifications.md @@ -2,6 +2,8 @@ This document provides the API specifications for the C++ library Proxy (version 3). All the documented concepts, classes, and functions are defined in the namespace `pro`. Unless otherwise specified, all facilities are [freestanding](https://en.cppreference.com/w/cpp/freestanding) by default. +*Since 3.4.0*: To support side-by-side installation of multiple major releases, each version of Proxy is wrapped in an inline namespace named after its major number. In a translation unit that includes both Proxy 3 and Proxy 4, the APIs can be referenced explicitly as `pro::v3::foo` or `pro::v4::foo` The current release exports `v3` as the inline (default) namespace, so unqualified names resolve to `pro::v3`. + ## Concepts | Name | Description | diff --git a/docs/weak_dispatch.md b/docs/weak_dispatch.md index 8e7cdf77..0633b5bb 100644 --- a/docs/weak_dispatch.md +++ b/docs/weak_dispatch.md @@ -28,7 +28,7 @@ In [Java](https://docs.oracle.com/javase/specs/jls/se23/html/jls-9.html#jls-9.4- #include #include -#include "proxy.h" +#include PRO_DEF_MEM_DISPATCH(MemAt, at); diff --git a/docs/weak_proxy.md b/docs/weak_proxy.md index d37662ef..f0681b77 100644 --- a/docs/weak_proxy.md +++ b/docs/weak_proxy.md @@ -10,14 +10,14 @@ using weak_proxy = proxy>; // 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` +## Member Types of `weak_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() 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` +## Member Constants of `weak_facade` | Name | Description | | ---------------------------------- | ------------------------------ | @@ -28,7 +28,7 @@ Class template `weak_facade` is a [facade](facade.md) type for weak pointers (e. ```cpp #include -#include "proxy.h" +#include struct Formattable : pro::facade_builder ::support_format diff --git a/include/proxy/proxy.h b/include/proxy/proxy.h new file mode 100644 index 00000000..7ebd2f38 --- /dev/null +++ b/include/proxy/proxy.h @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#ifndef _MSFT_PROXY_ +#define _MSFT_PROXY_ + +#include "v3/proxy.h" // IWYU pragma: export + +#endif // _MSFT_PROXY_ diff --git a/proxy.h b/include/proxy/v3/proxy.h similarity index 88% rename from proxy.h rename to include/proxy/v3/proxy.h index 9ba1c9e2..79f5d2c6 100644 --- a/proxy.h +++ b/include/proxy/v3/proxy.h @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -#ifndef _MSFT_PROXY_ -#define _MSFT_PROXY_ +#ifndef _MSFT_PROXY3_ +#define _MSFT_PROXY3_ #include #include @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -42,26 +43,26 @@ #endif // __cpp_exceptions >= 199711L #if __cpp_static_call_operator >= 202207L -#define ___PRO_STATIC_CALL(__R, ...) static __R operator()(__VA_ARGS__) +#define ___PRO3_STATIC_CALL(__R, ...) static __R operator()(__VA_ARGS__) #else -#define ___PRO_STATIC_CALL(__R, ...) __R operator()(__VA_ARGS__) const +#define ___PRO3_STATIC_CALL(__R, ...) __R operator()(__VA_ARGS__) const #endif // __cpp_static_call_operator >= 202207L #ifdef _MSC_VER -#define ___PRO_ENFORCE_EBO __declspec(empty_bases) +#define ___PRO3_ENFORCE_EBO __declspec(empty_bases) #else -#define ___PRO_ENFORCE_EBO +#define ___PRO3_ENFORCE_EBO #endif // _MSC_VER #ifdef NDEBUG -#define ___PRO_DEBUG(...) +#define ___PRO3_DEBUG(...) #else -#define ___PRO_DEBUG(...) __VA_ARGS__ +#define ___PRO3_DEBUG(...) __VA_ARGS__ #endif // NDEBUG -#define __msft_lib_proxy 202503L +#define __msft_lib_proxy3 202505L -namespace pro { +namespace pro::inline v3 { namespace details { @@ -126,7 +127,7 @@ template concept facade = details::basic_facade_traits::applicable; template struct proxy_indirect_accessor; -template class ___PRO_ENFORCE_EBO proxy; +template class ___PRO3_ENFORCE_EBO proxy; namespace details { @@ -482,14 +483,14 @@ struct refl_traits { struct copy_dispatch { template - ___PRO_STATIC_CALL(void, T&& self, proxy& rhs) + ___PRO3_STATIC_CALL(void, T&& self, proxy& rhs) noexcept(std::is_nothrow_constructible_v, T>) requires(std::is_constructible_v, T>) { std::construct_at(&rhs, std::forward(self)); } }; struct destroy_dispatch { template - ___PRO_STATIC_CALL(void, T& self) noexcept(std::is_nothrow_destructible_v) + ___PRO3_STATIC_CALL(void, T& self) noexcept(std::is_nothrow_destructible_v) requires(std::is_destructible_v) { std::destroy_at(&self); } }; template @@ -504,9 +505,9 @@ template using lifetime_meta_t = typename lifetime_meta_traits::type; template -class ___PRO_ENFORCE_EBO composite_accessor_impl : public As... { - template friend class pro::proxy; - template friend struct pro::proxy_indirect_accessor; +class ___PRO3_ENFORCE_EBO composite_accessor_impl : public As... { + template friend class pro::v3::proxy; + template friend struct pro::v3::proxy_indirect_accessor; composite_accessor_impl() noexcept = default; composite_accessor_impl(const composite_accessor_impl&) noexcept = default; @@ -933,7 +934,7 @@ class proxy : public details::facade_traits::direct_accessor, static_assert(_Traits::applicable); public: - proxy() noexcept { ___PRO_DEBUG(std::ignore = &_symbol_guard;) } + proxy() noexcept { ___PRO3_DEBUG(std::ignore = &_symbol_guard;) } proxy(std::nullptr_t) noexcept : proxy() {} proxy(const proxy&) noexcept requires(F::constraints.copyability == constraint_level::trivial) = default; @@ -1106,7 +1107,7 @@ class proxy : public details::facade_traits::direct_accessor, return result; } -___PRO_DEBUG( +___PRO3_DEBUG( static inline void _symbol_guard(proxy& self, const proxy& cself) noexcept { self.operator->(); *self; *std::move(self); cself.operator->(); *cself; *std::move(cself); @@ -1181,7 +1182,7 @@ class indirect_ptr { }; template -class ___PRO_ENFORCE_EBO allocated_ptr +class ___PRO3_ENFORCE_EBO allocated_ptr : private alloc_aware, public indirect_ptr> { public: template @@ -1203,7 +1204,7 @@ class ___PRO_ENFORCE_EBO allocated_ptr }; template -struct ___PRO_ENFORCE_EBO compact_ptr_storage +struct ___PRO3_ENFORCE_EBO compact_ptr_storage : alloc_aware, inplace_ptr { template explicit compact_ptr_storage(const Alloc& alloc, Args&&... args) @@ -1231,7 +1232,7 @@ class compact_ptr : public indirect_ptr> { struct shared_compact_ptr_storage_base { std::atomic_long ref_count = 1; }; template -struct ___PRO_ENFORCE_EBO shared_compact_ptr_storage +struct ___PRO3_ENFORCE_EBO shared_compact_ptr_storage : shared_compact_ptr_storage_base, alloc_aware, inplace_ptr { template explicit shared_compact_ptr_storage(const Alloc& alloc, Args&&... args) @@ -1523,120 +1524,125 @@ constexpr proxy make_proxy_shared(T&& value) #if __cpp_rtti >= 199711L class bad_proxy_cast : public std::bad_cast { public: - char const* what() const noexcept override { return "pro::bad_proxy_cast"; } + char const* what() const noexcept override + { return "pro::v3::bad_proxy_cast"; } }; #endif // __cpp_rtti >= 199711L -#define ___PRO_DIRECT_FUNC_IMPL(...) \ +#define ___PRO3_DIRECT_FUNC_IMPL(...) \ noexcept(noexcept(__VA_ARGS__)) requires(requires { __VA_ARGS__; }) \ { return __VA_ARGS__; } -#define ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(__MACRO, ...) \ +#define ___PRO3_DEF_MEM_ACCESSOR_TEMPLATE(__MACRO, ...) \ template \ - struct ___PRO_ENFORCE_EBO accessor { accessor() = delete; }; \ + struct ___PRO3_ENFORCE_EBO accessor { accessor() = delete; }; \ template \ 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>::__VA_ARGS__...; }; \ - __MACRO(, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \ - __MACRO(noexcept, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \ - __MACRO(&, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \ - __MACRO(& noexcept, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \ - __MACRO(&&, ::pro::access_proxy<__F>(::std::move(*this)), __VA_ARGS__); \ - __MACRO(&& noexcept, ::pro::access_proxy<__F>(::std::move(*this)), \ + __MACRO(, ::pro::v3::access_proxy<__F>(*this), __VA_ARGS__); \ + __MACRO(noexcept, ::pro::v3::access_proxy<__F>(*this), __VA_ARGS__); \ + __MACRO(&, ::pro::v3::access_proxy<__F>(*this), __VA_ARGS__); \ + __MACRO(& noexcept, ::pro::v3::access_proxy<__F>(*this), __VA_ARGS__); \ + __MACRO(&&, ::pro::v3::access_proxy<__F>(::std::move(*this)), \ __VA_ARGS__); \ - __MACRO(const, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \ - __MACRO(const noexcept, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \ - __MACRO(const&, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \ - __MACRO(const& noexcept, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \ - __MACRO(const&&, ::pro::access_proxy<__F>(::std::move(*this)), \ + __MACRO(&& noexcept, ::pro::v3::access_proxy<__F>(::std::move(*this)), \ __VA_ARGS__); \ - __MACRO(const&& noexcept, ::pro::access_proxy<__F>(::std::move(*this)), \ - __VA_ARGS__); + __MACRO(const, ::pro::v3::access_proxy<__F>(*this), __VA_ARGS__); \ + __MACRO(const noexcept, ::pro::v3::access_proxy<__F>(*this), \ + __VA_ARGS__); \ + __MACRO(const&, ::pro::v3::access_proxy<__F>(*this), __VA_ARGS__); \ + __MACRO(const& noexcept, ::pro::v3::access_proxy<__F>(*this), \ + __VA_ARGS__); \ + __MACRO(const&&, ::pro::v3::access_proxy<__F>(::std::move(*this)), \ + __VA_ARGS__); \ + __MACRO(const&& noexcept, ::pro::v3::access_proxy<__F>( \ + ::std::move(*this)), __VA_ARGS__); -#define ___PRO_ADL_ARG ::pro::details::adl_accessor_arg_t<__F, __IsDirect> -#define ___PRO_DEF_FREE_ACCESSOR_TEMPLATE(__MACRO, ...) \ +#define ___PRO3_ADL_ARG ::pro::v3::details::adl_accessor_arg_t<__F, __IsDirect> +#define ___PRO3_DEF_FREE_ACCESSOR_TEMPLATE(__MACRO, ...) \ template \ - struct ___PRO_ENFORCE_EBO accessor { accessor() = delete; }; \ + struct ___PRO3_ENFORCE_EBO accessor { accessor() = delete; }; \ template \ requires(sizeof...(__Os) > 1u && (::std::is_constructible_v< \ accessor<__F, __IsDirect, __D, __Os>> && ...)) \ struct accessor<__F, __IsDirect, __D, __Os...> \ : accessor<__F, __IsDirect, __D, __Os>... {}; \ - __MACRO(,, ___PRO_ADL_ARG& __self, ::pro::access_proxy<__F>(__self), \ + __MACRO(,, ___PRO3_ADL_ARG& __self, ::pro::v3::access_proxy<__F>(__self), \ __VA_ARGS__); \ - __MACRO(noexcept, noexcept, ___PRO_ADL_ARG& __self, \ - ::pro::access_proxy<__F>(__self), __VA_ARGS__); \ - __MACRO(&,, ___PRO_ADL_ARG& __self, ::pro::access_proxy<__F>(__self), \ + __MACRO(noexcept, noexcept, ___PRO3_ADL_ARG& __self, \ + ::pro::v3::access_proxy<__F>(__self), __VA_ARGS__); \ + __MACRO(&,, ___PRO3_ADL_ARG& __self, ::pro::v3::access_proxy<__F>(__self), \ __VA_ARGS__); \ - __MACRO(& noexcept, noexcept, ___PRO_ADL_ARG& __self, \ - ::pro::access_proxy<__F>(__self), __VA_ARGS__); \ - __MACRO(&&,, ___PRO_ADL_ARG&& __self, ::pro::access_proxy<__F>( \ + __MACRO(& noexcept, noexcept, ___PRO3_ADL_ARG& __self, \ + ::pro::v3::access_proxy<__F>(__self), __VA_ARGS__); \ + __MACRO(&&,, ___PRO3_ADL_ARG&& __self, ::pro::v3::access_proxy<__F>( \ ::std::forward(__self)), __VA_ARGS__); \ - __MACRO(&& noexcept, noexcept, ___PRO_ADL_ARG&& __self, \ - ::pro::access_proxy<__F>(::std::forward(__self)), \ - __VA_ARGS__); \ - __MACRO(const,, const ___PRO_ADL_ARG& __self, \ - ::pro::access_proxy<__F>(__self), __VA_ARGS__); \ - __MACRO(const noexcept, noexcept, const ___PRO_ADL_ARG& __self, \ - ::pro::access_proxy<__F>(__self), __VA_ARGS__); \ - __MACRO(const&,, const ___PRO_ADL_ARG& __self, \ - ::pro::access_proxy<__F>(__self), __VA_ARGS__); \ - __MACRO(const& noexcept, noexcept, const ___PRO_ADL_ARG& __self, \ - ::pro::access_proxy<__F>(__self), __VA_ARGS__); \ - __MACRO(const&&,, const ___PRO_ADL_ARG&& __self, ::pro::access_proxy<__F>( \ - ::std::forward(__self)), __VA_ARGS__); \ - __MACRO(const&& noexcept, noexcept, const ___PRO_ADL_ARG&& __self, \ - ::pro::access_proxy<__F>(::std::forward(__self)), \ - __VA_ARGS__); - -#define ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(...) \ - ___PRO_DEBUG( \ + __MACRO(&& noexcept, noexcept, ___PRO3_ADL_ARG&& __self, \ + ::pro::v3::access_proxy<__F>( \ + ::std::forward(__self)), __VA_ARGS__); \ + __MACRO(const,, const ___PRO3_ADL_ARG& __self, \ + ::pro::v3::access_proxy<__F>(__self), __VA_ARGS__); \ + __MACRO(const noexcept, noexcept, const ___PRO3_ADL_ARG& __self, \ + ::pro::v3::access_proxy<__F>(__self), __VA_ARGS__); \ + __MACRO(const&,, const ___PRO3_ADL_ARG& __self, \ + ::pro::v3::access_proxy<__F>(__self), __VA_ARGS__); \ + __MACRO(const& noexcept, noexcept, const ___PRO3_ADL_ARG& __self, \ + ::pro::v3::access_proxy<__F>(__self), __VA_ARGS__); \ + __MACRO(const&&,, const ___PRO3_ADL_ARG&& __self, \ + ::pro::v3::access_proxy<__F>( \ + ::std::forward(__self)), __VA_ARGS__); \ + __MACRO(const&& noexcept, noexcept, const ___PRO3_ADL_ARG&& __self, \ + ::pro::v3::access_proxy<__F>( \ + ::std::forward(__self)), __VA_ARGS__); + +#define ___PRO3_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(...) \ + ___PRO3_DEBUG( \ accessor() noexcept { ::std::ignore = &accessor::__VA_ARGS__; }) -#define ___PRO_EXPAND_IMPL(__X) __X -#define ___PRO_EXPAND_MACRO_IMPL(__MACRO, __1, __2, __3, __NAME, ...) \ +#define ___PRO3_EXPAND_IMPL(__X) __X +#define ___PRO3_EXPAND_MACRO_IMPL(__MACRO, __1, __2, __3, __NAME, ...) \ __MACRO##_##__NAME -#define ___PRO_EXPAND_MACRO(__MACRO, ...) \ - ___PRO_EXPAND_IMPL(___PRO_EXPAND_MACRO_IMPL( \ +#define ___PRO3_EXPAND_MACRO(__MACRO, ...) \ + ___PRO3_EXPAND_IMPL(___PRO3_EXPAND_MACRO_IMPL( \ __MACRO, __VA_ARGS__, 3, 2)(__VA_ARGS__)) -#define ___PRO_DEF_MEM_ACCESSOR(__Q, __SELF, ...) \ +#define ___PRO3_DEF_MEM_ACCESSOR(__Q, __SELF, ...) \ template \ struct accessor<__F, __IsDirect, __D, __R(__Args...) __Q> { \ - ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \ + ___PRO3_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \ __R __VA_ARGS__(__Args... __args) __Q { \ - return ::pro::proxy_invoke<__IsDirect, __D, __R(__Args...) __Q>( \ + return ::pro::v3::proxy_invoke<__IsDirect, __D, __R(__Args...) __Q>( \ __SELF, ::std::forward<__Args>(__args)...); \ } \ } -#define ___PRO_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) \ +#define ___PRO3_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) \ struct __NAME { \ template \ - ___PRO_STATIC_CALL(decltype(auto), __T&& __self, __Args&&... __args) \ - ___PRO_DIRECT_FUNC_IMPL(::std::forward<__T>(__self) \ + ___PRO3_STATIC_CALL(decltype(auto), __T&& __self, __Args&&... __args) \ + ___PRO3_DIRECT_FUNC_IMPL(::std::forward<__T>(__self) \ .__FUNC(::std::forward<__Args>(__args)...)) \ - ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_MEM_ACCESSOR, __FNAME) \ + ___PRO3_DEF_MEM_ACCESSOR_TEMPLATE(___PRO3_DEF_MEM_ACCESSOR, __FNAME) \ } -#define ___PRO_DEF_MEM_DISPATCH_2(__NAME, __FUNC) \ - ___PRO_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FUNC) -#define ___PRO_DEF_MEM_DISPATCH_3(__NAME, __FUNC, __FNAME) \ - ___PRO_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) -#define PRO_DEF_MEM_DISPATCH(__NAME, ...) \ - ___PRO_EXPAND_MACRO(___PRO_DEF_MEM_DISPATCH, __NAME, __VA_ARGS__) - -#define ___PRO_DEF_FREE_ACCESSOR(__Q, __NE, __SELF_ARG, __SELF, ...) \ +#define ___PRO3_DEF_MEM_DISPATCH_2(__NAME, __FUNC) \ + ___PRO3_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FUNC) +#define ___PRO3_DEF_MEM_DISPATCH_3(__NAME, __FUNC, __FNAME) \ + ___PRO3_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) +#define PRO3_DEF_MEM_DISPATCH(__NAME, ...) \ + ___PRO3_EXPAND_MACRO(___PRO3_DEF_MEM_DISPATCH, __NAME, __VA_ARGS__) + +#define ___PRO3_DEF_FREE_ACCESSOR(__Q, __NE, __SELF_ARG, __SELF, ...) \ template \ struct accessor<__F, __IsDirect, __D, __R(__Args...) __Q> { \ friend __R __VA_ARGS__(__SELF_ARG, __Args... __args) __NE { \ - return ::pro::proxy_invoke<__IsDirect, __D, __R(__Args...) __Q>( \ + return ::pro::v3::proxy_invoke<__IsDirect, __D, __R(__Args...) __Q>( \ __SELF, ::std::forward<__Args>(__args)...); \ } \ -___PRO_DEBUG( \ +___PRO3_DEBUG( \ accessor() noexcept { ::std::ignore = &_symbol_guard; } \ \ private: \ @@ -1646,35 +1652,35 @@ ___PRO_DEBUG( \ } \ ) \ } -#define ___PRO_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) \ +#define ___PRO3_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) \ struct __NAME { \ template \ - ___PRO_STATIC_CALL(decltype(auto), __T&& __self, __Args&&... __args) \ - ___PRO_DIRECT_FUNC_IMPL(__FUNC(::std::forward<__T>(__self), \ + ___PRO3_STATIC_CALL(decltype(auto), __T&& __self, __Args&&... __args) \ + ___PRO3_DIRECT_FUNC_IMPL(__FUNC(::std::forward<__T>(__self), \ ::std::forward<__Args>(__args)...)) \ - ___PRO_DEF_FREE_ACCESSOR_TEMPLATE(___PRO_DEF_FREE_ACCESSOR, __FNAME) \ + ___PRO3_DEF_FREE_ACCESSOR_TEMPLATE(___PRO3_DEF_FREE_ACCESSOR, __FNAME) \ } -#define ___PRO_DEF_FREE_DISPATCH_2(__NAME, __FUNC) \ - ___PRO_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FUNC) -#define ___PRO_DEF_FREE_DISPATCH_3(__NAME, __FUNC, __FNAME) \ - ___PRO_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) -#define PRO_DEF_FREE_DISPATCH(__NAME, ...) \ - ___PRO_EXPAND_MACRO(___PRO_DEF_FREE_DISPATCH, __NAME, __VA_ARGS__) - -#define ___PRO_DEF_FREE_AS_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) \ +#define ___PRO3_DEF_FREE_DISPATCH_2(__NAME, __FUNC) \ + ___PRO3_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FUNC) +#define ___PRO3_DEF_FREE_DISPATCH_3(__NAME, __FUNC, __FNAME) \ + ___PRO3_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) +#define PRO3_DEF_FREE_DISPATCH(__NAME, ...) \ + ___PRO3_EXPAND_MACRO(___PRO3_DEF_FREE_DISPATCH, __NAME, __VA_ARGS__) + +#define ___PRO3_DEF_FREE_AS_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) \ struct __NAME { \ template \ - ___PRO_STATIC_CALL(decltype(auto), __T&& __self, __Args&&... __args) \ - ___PRO_DIRECT_FUNC_IMPL(__FUNC(::std::forward<__T>(__self), \ + ___PRO3_STATIC_CALL(decltype(auto), __T&& __self, __Args&&... __args) \ + ___PRO3_DIRECT_FUNC_IMPL(__FUNC(::std::forward<__T>(__self), \ ::std::forward<__Args>(__args)...)) \ - ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_MEM_ACCESSOR, __FNAME) \ + ___PRO3_DEF_MEM_ACCESSOR_TEMPLATE(___PRO3_DEF_MEM_ACCESSOR, __FNAME) \ } -#define ___PRO_DEF_FREE_AS_MEM_DISPATCH_2(__NAME, __FUNC) \ - ___PRO_DEF_FREE_AS_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FUNC) -#define ___PRO_DEF_FREE_AS_MEM_DISPATCH_3(__NAME, __FUNC, __FNAME) \ - ___PRO_DEF_FREE_AS_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) -#define PRO_DEF_FREE_AS_MEM_DISPATCH(__NAME, ...) \ - ___PRO_EXPAND_MACRO(___PRO_DEF_FREE_AS_MEM_DISPATCH, __NAME, __VA_ARGS__) +#define ___PRO3_DEF_FREE_AS_MEM_DISPATCH_2(__NAME, __FUNC) \ + ___PRO3_DEF_FREE_AS_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FUNC) +#define ___PRO3_DEF_FREE_AS_MEM_DISPATCH_3(__NAME, __FUNC, __FNAME) \ + ___PRO3_DEF_FREE_AS_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) +#define PRO3_DEF_FREE_AS_MEM_DISPATCH(__NAME, ...) \ + ___PRO3_EXPAND_MACRO(___PRO3_DEF_FREE_AS_MEM_DISPATCH, __NAME, __VA_ARGS__) namespace details { @@ -1685,7 +1691,7 @@ using adl_accessor_arg_t = #define ___PRO_DEF_CAST_ACCESSOR(Q, SELF, ...) \ template \ struct accessor<__F, __IsDirect, __D, T() Q> { \ - ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(operator T) \ + ___PRO3_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(operator T) \ explicit(Expl) operator T() Q { \ if constexpr (Nullable) { \ if (!SELF.has_value()) { return nullptr; } \ @@ -1695,14 +1701,14 @@ using adl_accessor_arg_t = } template struct cast_dispatch_base { - ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_CAST_ACCESSOR, + ___PRO3_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_CAST_ACCESSOR, operator typename overload_traits<__Os>::return_type) }; #undef ___PRO_DEF_CAST_ACCESSOR struct upward_conversion_dispatch : cast_dispatch_base { template - ___PRO_STATIC_CALL(T&&, T&& self) noexcept { return std::forward(self); } + ___PRO3_STATIC_CALL(T&&, T&& self) noexcept { return std::forward(self); } }; template @@ -1876,7 +1882,7 @@ using merge_facade_conv_t = typename add_upward_conversion_conv< struct proxy_view_dispatch : cast_dispatch_base { template - ___PRO_STATIC_CALL(auto, T& value) noexcept + ___PRO3_STATIC_CALL(auto, T& value) noexcept requires(requires { { std::addressof(*value) } noexcept; }) { return observer_ptr @@ -1969,7 +1975,7 @@ sign(const char (&str)[N]) -> sign; struct weak_conversion_dispatch : cast_dispatch_base { template - ___PRO_STATIC_CALL(auto, const P& self) noexcept + ___PRO3_STATIC_CALL(auto, const P& self) noexcept requires( requires(const typename P::weak_type& w) { { w.lock() } noexcept -> std::same_as

; } && @@ -2000,7 +2006,7 @@ template auto weak_lock_impl(const P& self) noexcept requires(requires { static_cast(self.lock()); }) { return nullable_ptr_adapter{self.lock()}; } -PRO_DEF_FREE_AS_MEM_DISPATCH(weak_mem_lock, weak_lock_impl, lock); +PRO3_DEF_FREE_AS_MEM_DISPATCH(weak_mem_lock, weak_lock_impl, lock); #if __STDC_HOSTED__ template struct format_overload_traits; @@ -2024,7 +2030,7 @@ struct format_dispatch { // std::formatter by std::is_default_constructible_v as per // [format.formatter.spec]. template - ___PRO_STATIC_CALL(OutIt, const T& self, std::basic_string_view spec, + ___PRO3_STATIC_CALL(OutIt, const T& self, std::basic_string_view spec, std::basic_format_context& fc) requires( #if __cpp_lib_format_ranges >= 202207L @@ -2098,7 +2104,7 @@ struct proxy_cast_accessor_impl { void(proxy_cast_context) Q> {} struct proxy_cast_dispatch { template - ___PRO_STATIC_CALL(void, T&& self, proxy_cast_context ctx) { + ___PRO3_STATIC_CALL(void, T&& self, proxy_cast_context ctx) { if (typeid(T) == *ctx.type_ptr) { if (ctx.is_ref) { if constexpr (std::is_lvalue_reference_v) { @@ -2114,7 +2120,7 @@ struct proxy_cast_dispatch { } } } - ___PRO_DEF_FREE_ACCESSOR_TEMPLATE(___PRO_DEF_PROXY_CAST_ACCESSOR) + ___PRO3_DEF_FREE_ACCESSOR_TEMPLATE(___PRO_DEF_PROXY_CAST_ACCESSOR) }; #undef ___PRO_DEF_PROXY_CAST_ACCESSOR @@ -2133,7 +2139,7 @@ struct proxy_typeid_reflector { const proxy_typeid_reflector& refl = proxy_reflect(p); return *refl.info; } -___PRO_DEBUG( +___PRO3_DEBUG( accessor() noexcept { std::ignore = &_symbol_guard; } private: @@ -2267,13 +2273,13 @@ struct operator_dispatch; #define ___PRO_DEF_LHS_LEFT_OP_ACCESSOR(Q, SELF, ...) \ template \ struct accessor<__F, __IsDirect, __D, R() Q> { \ - ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \ + ___PRO3_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \ R __VA_ARGS__() Q { return proxy_invoke<__IsDirect, __D, R() Q>(SELF); } \ } #define ___PRO_DEF_LHS_ANY_OP_ACCESSOR(Q, SELF, ...) \ template \ struct accessor<__F, __IsDirect, __D, R(Args...) Q> { \ - ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \ + ___PRO3_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \ R __VA_ARGS__(Args... args) Q { \ return proxy_invoke<__IsDirect, __D, R(Args...) Q>( \ SELF, std::forward(args)...); \ @@ -2284,19 +2290,19 @@ struct operator_dispatch; #define ___PRO_DEF_LHS_ALL_OP_ACCESSOR ___PRO_DEF_LHS_ANY_OP_ACCESSOR #define ___PRO_LHS_LEFT_OP_DISPATCH_BODY_IMPL(...) \ template \ - ___PRO_STATIC_CALL(decltype(auto), T&& self) \ - ___PRO_DIRECT_FUNC_IMPL(__VA_ARGS__ std::forward(self)) + ___PRO3_STATIC_CALL(decltype(auto), T&& self) \ + ___PRO3_DIRECT_FUNC_IMPL(__VA_ARGS__ std::forward(self)) #define ___PRO_LHS_UNARY_OP_DISPATCH_BODY_IMPL(...) \ template \ - ___PRO_STATIC_CALL(decltype(auto), T&& self) \ - ___PRO_DIRECT_FUNC_IMPL(__VA_ARGS__ std::forward(self)) \ + ___PRO3_STATIC_CALL(decltype(auto), T&& self) \ + ___PRO3_DIRECT_FUNC_IMPL(__VA_ARGS__ std::forward(self)) \ template \ - ___PRO_STATIC_CALL(decltype(auto), T&& self, int) \ - ___PRO_DIRECT_FUNC_IMPL(std::forward(self) __VA_ARGS__) + ___PRO3_STATIC_CALL(decltype(auto), T&& self, int) \ + ___PRO3_DIRECT_FUNC_IMPL(std::forward(self) __VA_ARGS__) #define ___PRO_LHS_BINARY_OP_DISPATCH_BODY_IMPL(...) \ template \ - ___PRO_STATIC_CALL(decltype(auto), T&& self, Arg&& arg) \ - ___PRO_DIRECT_FUNC_IMPL( \ + ___PRO3_STATIC_CALL(decltype(auto), T&& self, Arg&& arg) \ + ___PRO3_DIRECT_FUNC_IMPL( \ std::forward(self) __VA_ARGS__ std::forward(arg)) #define ___PRO_LHS_ALL_OP_DISPATCH_BODY_IMPL(...) \ ___PRO_LHS_LEFT_OP_DISPATCH_BODY_IMPL(__VA_ARGS__) \ @@ -2305,7 +2311,7 @@ struct operator_dispatch; template <> \ struct operator_dispatch<#__VA_ARGS__, false> { \ ___PRO_LHS_##TYPE##_OP_DISPATCH_BODY_IMPL(__VA_ARGS__) \ - ___PRO_DEF_MEM_ACCESSOR_TEMPLATE( \ + ___PRO3_DEF_MEM_ACCESSOR_TEMPLATE( \ ___PRO_DEF_LHS_##TYPE##_OP_ACCESSOR, operator __VA_ARGS__) \ }; @@ -2316,7 +2322,7 @@ struct operator_dispatch; return proxy_invoke<__IsDirect, __D, R(Arg) Q>( \ SELF, std::forward(arg)); \ } \ -___PRO_DEBUG( \ +___PRO3_DEBUG( \ accessor() noexcept { std::ignore = &_symbol_guard; } \ \ private: \ @@ -2330,10 +2336,10 @@ ___PRO_DEBUG( \ template <> \ struct operator_dispatch<#__VA_ARGS__, true> { \ template \ - ___PRO_STATIC_CALL(decltype(auto), T&& self, Arg&& arg) \ - ___PRO_DIRECT_FUNC_IMPL( \ + ___PRO3_STATIC_CALL(decltype(auto), T&& self, Arg&& arg) \ + ___PRO3_DIRECT_FUNC_IMPL( \ std::forward(arg) __VA_ARGS__ std::forward(self)) \ - ___PRO_DEF_FREE_ACCESSOR_TEMPLATE( \ + ___PRO3_DEF_FREE_ACCESSOR_TEMPLATE( \ ___PRO_DEF_RHS_OP_ACCESSOR, __VA_ARGS__) \ }; @@ -2348,7 +2354,7 @@ ___PRO_DEBUG( \ #define ___PRO_DEF_LHS_ASSIGNMENT_OP_ACCESSOR(Q, SELF, ...) \ template \ struct accessor<__F, __IsDirect, __D, R(Arg) Q> { \ - ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \ + ___PRO3_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \ decltype(auto) __VA_ARGS__(Arg arg) Q { \ proxy_invoke<__IsDirect, __D, R(Arg) Q>(SELF, std::forward(arg)); \ if constexpr (__IsDirect) { \ @@ -2365,7 +2371,7 @@ ___PRO_DEBUG( \ proxy_invoke<__IsDirect, __D, R(Arg&) Q>(SELF, arg); \ return arg; \ } \ -___PRO_DEBUG( \ +___PRO3_DEBUG( \ accessor() noexcept { std::ignore = &_symbol_guard; } \ \ private: \ @@ -2377,20 +2383,20 @@ ___PRO_DEBUG( \ template <> \ struct operator_dispatch<#__VA_ARGS__, false> { \ template \ - ___PRO_STATIC_CALL(decltype(auto), T&& self, Arg&& arg) \ - ___PRO_DIRECT_FUNC_IMPL(std::forward(self) __VA_ARGS__ \ + ___PRO3_STATIC_CALL(decltype(auto), T&& self, Arg&& arg) \ + ___PRO3_DIRECT_FUNC_IMPL(std::forward(self) __VA_ARGS__ \ std::forward(arg)) \ - ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_LHS_ASSIGNMENT_OP_ACCESSOR, \ + ___PRO3_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_LHS_ASSIGNMENT_OP_ACCESSOR, \ operator __VA_ARGS__) \ }; \ template <> \ struct operator_dispatch<#__VA_ARGS__, true> { \ template \ - ___PRO_STATIC_CALL(decltype(auto), T&& self, Arg&& arg) \ - ___PRO_DIRECT_FUNC_IMPL( \ + ___PRO3_STATIC_CALL(decltype(auto), T&& self, Arg&& arg) \ + ___PRO3_DIRECT_FUNC_IMPL( \ std::forward(arg) __VA_ARGS__ std::forward(self)) \ - ___PRO_DEF_FREE_ACCESSOR_TEMPLATE(___PRO_DEF_RHS_ASSIGNMENT_OP_ACCESSOR, \ - __VA_ARGS__) \ + ___PRO3_DEF_FREE_ACCESSOR_TEMPLATE( \ + ___PRO_DEF_RHS_ASSIGNMENT_OP_ACCESSOR, __VA_ARGS__) \ }; ___PRO_EXTENDED_BINARY_OP_DISPATCH_IMPL(+) @@ -2431,24 +2437,24 @@ ___PRO_BINARY_OP_DISPATCH_IMPL(->*) template <> struct operator_dispatch<"()", false> { template - ___PRO_STATIC_CALL(decltype(auto), T&& self, Args&&... args) - ___PRO_DIRECT_FUNC_IMPL( + ___PRO3_STATIC_CALL(decltype(auto), T&& self, Args&&... args) + ___PRO3_DIRECT_FUNC_IMPL( std::forward(self)(std::forward(args)...)) - ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_LHS_ANY_OP_ACCESSOR, operator()) + ___PRO3_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_LHS_ANY_OP_ACCESSOR, operator()) }; template <> struct operator_dispatch<"[]", false> { #if __cpp_multidimensional_subscript >= 202110L template - ___PRO_STATIC_CALL(decltype(auto), T&& self, Args&&... args) - ___PRO_DIRECT_FUNC_IMPL( + ___PRO3_STATIC_CALL(decltype(auto), T&& self, Args&&... args) + ___PRO3_DIRECT_FUNC_IMPL( std::forward(self)[std::forward(args)...]) #else template - ___PRO_STATIC_CALL(decltype(auto), T&& self, Arg&& arg) - ___PRO_DIRECT_FUNC_IMPL(std::forward(self)[std::forward(arg)]) + ___PRO3_STATIC_CALL(decltype(auto), T&& self, Arg&& arg) + ___PRO3_DIRECT_FUNC_IMPL(std::forward(self)[std::forward(arg)]) #endif // __cpp_multidimensional_subscript >= 202110L - ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_LHS_ANY_OP_ACCESSOR, operator[]) + ___PRO3_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_LHS_ANY_OP_ACCESSOR, operator[]) }; #undef ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL @@ -2472,25 +2478,26 @@ struct operator_dispatch<"[]", false> { struct implicit_conversion_dispatch : details::cast_dispatch_base { template - ___PRO_STATIC_CALL(T&&, T&& self) noexcept { return std::forward(self); } + ___PRO3_STATIC_CALL(T&&, T&& self) noexcept { return std::forward(self); } }; struct explicit_conversion_dispatch : details::cast_dispatch_base { template - ___PRO_STATIC_CALL(auto, T&& self) noexcept + ___PRO3_STATIC_CALL(auto, T&& self) noexcept { return details::explicit_conversion_adapter{std::forward(self)}; } }; using conversion_dispatch = explicit_conversion_dispatch; class not_implemented : public std::exception { public: - char const* what() const noexcept override { return "pro::not_implemented"; } + char const* what() const noexcept override + { return "pro::v3::not_implemented"; } }; template struct weak_dispatch : D { using D::operator(); template - [[noreturn]] ___PRO_STATIC_CALL(details::wildcard, std::nullptr_t, Args&&...) + [[noreturn]] ___PRO3_STATIC_CALL(details::wildcard, std::nullptr_t, Args&&...) { ___PRO_THROW(not_implemented{}); } }; @@ -2499,8 +2506,9 @@ struct weak_dispatch : D { "Use pro::weak_dispatch<" #__D "> instead.")]] __NAME : __D { \ using __D::operator(); \ template \ - ___PRO_STATIC_CALL(decltype(auto), ::std::nullptr_t, __Args&&... __args) \ - ___PRO_DIRECT_FUNC_IMPL(__FUNC(::std::forward<__Args>(__args)...)) \ + ___PRO3_STATIC_CALL(decltype(auto), \ + ::std::nullptr_t, __Args&&... __args) \ + ___PRO3_DIRECT_FUNC_IMPL(__FUNC(::std::forward<__Args>(__args)...)) \ } } // namespace pro @@ -2508,10 +2516,11 @@ struct weak_dispatch : D { #if __STDC_HOSTED__ namespace std { -template - requires(pro::details::facade_traits::template is_invocable>) -struct formatter, CharT> { +template + requires(pro::v3::details::facade_traits::template is_invocable< + false, pro::v3::details::format_dispatch, + pro::v3::details::format_overload_t>) +struct formatter, CharT> { constexpr auto parse(basic_format_parse_context& pc) { for (auto it = pc.begin(); it != pc.end(); ++it) { if (*it == '}') { @@ -2523,12 +2532,12 @@ struct formatter, CharT> { } template - OutIt format(const pro::proxy_indirect_accessor& ia, + OutIt format(const pro::v3::proxy_indirect_accessor& ia, basic_format_context& fc) const { - auto& p = pro::access_proxy(ia); + auto& p = pro::v3::access_proxy(ia); if (!p.has_value()) { ___PRO_THROW(format_error{"null proxy"}); } - return pro::proxy_invoke>(p, spec_, fc); + return pro::v3::proxy_invoke>(p, spec_, fc); } private: @@ -2538,7 +2547,60 @@ struct formatter, CharT> { } // namespace std #endif // __STDC_HOSTED__ +// Version-less macro aliases + +#define ___PRO3_AMBIGUOUS_MACRO_DIAGNOSTIC_ASSERT(__NAME, \ + __VERSION_QUALIFIED_NAME) \ + static_assert(false, "The use of macro `" #__NAME "` is ambiguous. \ +Are multiple different versions of Proxy library included at the same time?\n\ +Note: To resolve this error: \n\ +- Either make sure that only one version of Proxy library is included within this file.\n\ +- Or use the `" #__VERSION_QUALIFIED_NAME \ + "` macro (note the `3` suffix) to explicitly \ +stick to a specific major version of the Proxy library.") + +#ifdef __msft_lib_proxy +#undef __msft_lib_proxy +#define __msft_lib_proxy \ + [] { \ + ___PRO3_AMBIGUOUS_MACRO_DIAGNOSTIC_ASSERT(__msft_lib_proxy, \ + __msft_lib_proxy3); \ + return 0L; \ + }() +#else +#define __msft_lib_proxy __msft_lib_proxy3 +#endif // __msft_lib_proxy + +#ifdef PRO_DEF_MEM_DISPATCH +#undef PRO_DEF_MEM_DISPATCH +#define PRO_DEF_MEM_DISPATCH(...) \ + ___PRO3_AMBIGUOUS_MACRO_DIAGNOSTIC_ASSERT(PRO_DEF_MEM_DISPATCH, \ + PRO3_DEF_MEM_DISPATCH) +#else +#define PRO_DEF_MEM_DISPATCH(name, ...) PRO3_DEF_MEM_DISPATCH(name, __VA_ARGS__) +#endif // PRO_DEF_MEM_DISPATCH + +#ifdef PRO_DEF_FREE_DISPATCH +#undef PRO_DEF_FREE_DISPATCH +#define PRO_DEF_FREE_DISPATCH(...) \ + ___PRO3_AMBIGUOUS_MACRO_DIAGNOSTIC_ASSERT(PRO_DEF_FREE_DISPATCH, \ + PRO3_DEF_FREE_DISPATCH) +#else +#define PRO_DEF_FREE_DISPATCH(name, ...) \ + PRO3_DEF_FREE_DISPATCH(name, __VA_ARGS__) +#endif // PRO_DEF_FREE_DISPATCH + +#ifdef PRO_DEF_FREE_AS_MEM_DISPATCH +#undef PRO_DEF_FREE_AS_MEM_DISPATCH +#define PRO_DEF_FREE_AS_MEM_DISPATCH(...) \ + ___PRO3_AMBIGUOUS_MACRO_DIAGNOSTIC_ASSERT(PRO_DEF_FREE_AS_MEM_DISPATCH, \ + PRO3_DEF_FREE_AS_MEM_DISPATCH) +#else +#define PRO_DEF_FREE_AS_MEM_DISPATCH(name, ...) \ + PRO3_DEF_FREE_AS_MEM_DISPATCH(name, __VA_ARGS__) +#endif // PRO_DEF_FREE_AS_MEM_DISPATCH + #undef ___PRO_THROW #undef ___PRO_NO_UNIQUE_ADDRESS_ATTRIBUTE -#endif // _MSFT_PROXY_ +#endif // _MSFT_PROXY3_ diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt deleted file mode 100644 index 29deb3ea..00000000 --- a/samples/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -project(msft_proxy_samples) - -file(GLOB_RECURSE SOURCES "*.cpp") - -foreach(SOURCE ${SOURCES}) - file(RELATIVE_PATH REL_PATH ${CMAKE_SOURCE_DIR} ${SOURCE}) - get_filename_component(DIR ${REL_PATH} DIRECTORY) - string(REPLACE "/" "_" DIR_UNDERSCORE ${DIR}) - get_filename_component(EXECUTABLE_NAME ${SOURCE} NAME_WE) - set(FULL_EXECUTABLE_NAME "${DIR_UNDERSCORE}_${EXECUTABLE_NAME}") - add_executable(${FULL_EXECUTABLE_NAME} ${SOURCE}) - target_link_libraries(${FULL_EXECUTABLE_NAME} PRIVATE msft_proxy) - if (MSVC) - target_compile_options(${FULL_EXECUTABLE_NAME} PRIVATE /W4) - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - target_compile_options(${FULL_EXECUTABLE_NAME} PRIVATE -Wall -Wextra -Wpedantic -Wno-c++2b-extensions) - else() - target_compile_options(${FULL_EXECUTABLE_NAME} PRIVATE -Wall -Wextra -Wpedantic) - endif() -endforeach() diff --git a/samples/PRO_DEF_FREE_AS_MEM_DISPATCH.cpp b/samples/PRO_DEF_FREE_AS_MEM_DISPATCH.cpp deleted file mode 100644 index eb807dca..00000000 --- a/samples/PRO_DEF_FREE_AS_MEM_DISPATCH.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from PRO_DEF_FREE_AS_MEM_DISPATCH.md. - -#include -#include - -#include "proxy.h" - -PRO_DEF_FREE_AS_MEM_DISPATCH(FreeToString, std::to_string, ToString); - -struct Stringable : pro::facade_builder - ::add_convention - ::build {}; - -int main() { - pro::proxy p = pro::make_proxy(123); - std::cout << p->ToString() << "\n"; // Prints "123" -} diff --git a/samples/PRO_DEF_FREE_DISPATCH.cpp b/samples/PRO_DEF_FREE_DISPATCH.cpp deleted file mode 100644 index 1648c5b2..00000000 --- a/samples/PRO_DEF_FREE_DISPATCH.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from PRO_DEF_FREE_DISPATCH.md. - -#include -#include - -#include "proxy.h" - -PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); - -struct Stringable : pro::facade_builder - ::add_convention - ::build {}; - -int main() { - pro::proxy p = pro::make_proxy(123); - std::cout << ToString(*p) << "\n"; // Prints "123" -} diff --git a/samples/PRO_DEF_MEM_DISPATCH.cpp b/samples/PRO_DEF_MEM_DISPATCH.cpp deleted file mode 100644 index 53af4bd1..00000000 --- a/samples/PRO_DEF_MEM_DISPATCH.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from PRO_DEF_MEM_DISPATCH.md. - -#include -#include -#include - -#include "proxy.h" - -PRO_DEF_MEM_DISPATCH(MemAt, at); - -struct Dictionary : pro::facade_builder - ::add_convention - ::build {}; - -int main() { - std::vector v{"hello", "world"}; - pro::proxy p = &v; - std::cout << p->at(1) << "\n"; // Prints "world" -} diff --git a/samples/PRO_DEF_WEAK_DISPATCH.cpp b/samples/PRO_DEF_WEAK_DISPATCH.cpp deleted file mode 100644 index 2ea7fb48..00000000 --- a/samples/PRO_DEF_WEAK_DISPATCH.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from PRO_DEF_WEAK_DISPATCH.md. - -#include -#include -#include - -#include "proxy.h" - -struct NotImplemented { - explicit NotImplemented(auto&&...) { throw std::runtime_error{ "Not implemented!" }; } - - template - operator T() const noexcept { std::terminate(); } // Or std::unreachable() in C++23 -}; - -PRO_DEF_MEM_DISPATCH(MemAt, at); -PRO_DEF_WEAK_DISPATCH(WeakMemAt, MemAt, NotImplemented); - -struct WeakDictionary : pro::facade_builder - ::add_convention - ::build {}; - -int main() { - std::vector v{"hello", "world"}; - pro::proxy p1 = &v; - std::cout << p1->at(1) << "\n"; // Prints "world" - pro::proxy p2 = pro::make_proxy(123); - try { - p2->at(1); - } catch (const std::runtime_error& e) { - std::cout << e.what() << "\n"; // Prints "Not implemented!" - } -} diff --git a/samples/access_proxy.cpp b/samples/access_proxy.cpp deleted file mode 100644 index 14e180f2..00000000 --- a/samples/access_proxy.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from access_proxy.md. - -#include -#include - -#include "proxy.h" - -PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); - -struct Stringable : pro::facade_builder - ::add_convention - ::build {}; - -int main() { - pro::proxy p = pro::make_proxy(123); - - // Invokes with accessibility API - std::cout << ToString(*p) << "\n"; // Prints "123" - - // How it works behind the scenes - using Accessor = FreeToString::accessor; - static_assert(std::is_base_of_v>); - Accessor& a = static_cast(*p); - pro::proxy& p2 = pro::access_proxy(a); - std::cout << std::boolalpha << (&p == &p2) << "\n"; // Prints "true" because access_proxy converts - // an accessor back to the original proxy - auto result = pro::proxy_invoke(p2); - std::cout << result << "\n"; // Prints "123" -} diff --git a/samples/allocate_proxy.cpp b/samples/allocate_proxy.cpp deleted file mode 100644 index 22878af6..00000000 --- a/samples/allocate_proxy.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from allocate_proxy.md. - -#include - -#include "proxy.h" - -// By default, the maximum pointer size defined by pro::facade_builder -// is 2 * sizeof(void*). This value can be overridden by `restrict_layout`. -struct Any : pro::facade_builder::build {}; - -int main() { - // sizeof(std::array) is usually greater than 2 * sizeof(void*), - // calling allocate_proxy has no limitation to the size and alignment of the target - using Target = std::array; - pro::proxy p1 = pro::allocate_proxy(std::allocator{}); -} diff --git a/samples/allocate_proxy_shared.cpp b/samples/allocate_proxy_shared.cpp deleted file mode 100644 index 41032aa8..00000000 --- a/samples/allocate_proxy_shared.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from allocate_proxy_shared.md. - -#include -#include - -#include "proxy.h" - -struct RttiAware : pro::facade_builder - ::support_copy - ::support_rtti - ::build {}; - -int main() { - std::pmr::unsynchronized_pool_resource pool; - std::pmr::polymorphic_allocator<> alloc{&pool}; - pro::proxy p1 = pro::allocate_proxy_shared(alloc, 1); - pro::proxy p2 = p1; - proxy_cast(*p1) += 2; - std::cout << proxy_cast(*p2) << "\n"; // Prints "3" -} diff --git a/samples/basic_facade_builder.cpp b/samples/basic_facade_builder.cpp deleted file mode 100644 index 2e82cbab..00000000 --- a/samples/basic_facade_builder.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from basic_facade_builder.md. - -#include - -#include "proxy.h" - -template -struct MovableCallable : pro::facade_builder - ::add_convention, Overloads...> - ::build {}; - -template -struct CopyableCallable : pro::facade_builder - ::support_copy - ::add_facade> - ::build {}; - -// MyFunction has similar functionality as std::function but supports multiple overloads -// MyMoveOnlyFunction has similar functionality as std::move_only_function but supports multiple overloads -template -using MyFunction = pro::proxy>; -template -using MyMoveOnlyFunction = pro::proxy>; - -int main() { - auto f = [](auto&&... v) { - std::cout << "f() called. Args: "; - ((std::cout << v << ":" << typeid(decltype(v)).name() << ", "), ...); - std::cout << "\n"; - }; - MyFunction p0{&f}; - (*p0)(123); // Prints "f() called. Args: 123:i," (assuming GCC) - MyMoveOnlyFunction p1{&f}; - (*p1)(); // Prints "f() called. Args:" - (*p1)(456); // Prints "f() called. Args: 456:i," - (*p1)(1.2); // Prints "f() called. Args: 1.2:d," -} diff --git a/samples/basic_facade_builder/add_convention.cpp b/samples/basic_facade_builder/add_convention.cpp deleted file mode 100644 index 7f0ed4f2..00000000 --- a/samples/basic_facade_builder/add_convention.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from add_convention.md. - -#include -#include -#include - -#include "proxy.h" - -PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); - -struct BasicStringable : pro::facade_builder - ::add_convention - ::build {}; - -struct Stringable : pro::facade_builder - ::add_facade - ::support_copy - ::add_direct_convention() &&> - ::build {}; - -int main() { - pro::proxy p1 = std::make_shared(123); - pro::proxy p2 = p1; - pro::proxy p3 = static_cast>(std::move(p2)); - pro::proxy p4 = std::move(p3); - // pro::proxy p5 = p4; // Won't compile - std::cout << ToString(*p4) << "\n"; // Prints "123" - std::cout << std::boolalpha << p3.has_value() << "\n"; // Prints "false" -} diff --git a/samples/basic_facade_builder/add_facade.cpp b/samples/basic_facade_builder/add_facade.cpp deleted file mode 100644 index 1b122f99..00000000 --- a/samples/basic_facade_builder/add_facade.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from add_facade.md. - -#include -#include - -#include "proxy.h" - -PRO_DEF_MEM_DISPATCH(MemSize, size); -PRO_DEF_MEM_DISPATCH(MemAt, at); -PRO_DEF_MEM_DISPATCH(MemEmplace, emplace); - -struct Copyable : pro::facade_builder - ::support_copy - ::build {}; - -struct BasicContainer : pro::facade_builder - ::add_convention - ::build {}; - -struct StringDictionary : pro::facade_builder - ::add_facade - ::add_facade - ::add_convention - ::build {}; - -struct MutableStringDictionary : pro::facade_builder - ::add_facade - ::add_convention - ::build {}; - -int main() { - pro::proxy p1 = - pro::make_proxy>(); - std::cout << p1->size() << "\n"; // Prints "0" - try { - std::cout << p1->at(123) << "\n"; // No output because the expression throws - } catch (const std::out_of_range& e) { - std::cerr << e.what() << "\n"; // Prints error message - } - p1->emplace(123, "lalala"); - auto p2 = p1; // Performs a deep copy - p2->emplace(456, "trivial"); - pro::proxy p3 = std::move(p2); // Performs an upward conversion from an rvalue reference - std::cout << p1->size() << "\n"; // Prints "1" - std::cout << p1->at(123) << "\n"; // Prints "lalala" - std::cout << std::boolalpha << p2.has_value() << "\n"; // Prints "false" because it is moved - std::cout << p3->size() << "\n"; // Prints "2" - std::cout << p3->at(123) << "\n"; // Prints "lalala" - std::cout << p3->at(456) << "\n"; // Prints "trivial" -} diff --git a/samples/basic_facade_builder/add_reflection.cpp b/samples/basic_facade_builder/add_reflection.cpp deleted file mode 100644 index e0b91e54..00000000 --- a/samples/basic_facade_builder/add_reflection.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from add_reflection.md. - -#include -#include - -#include "proxy.h" - -struct LayoutReflector { - public: - template - constexpr explicit LayoutReflector(std::in_place_type_t) - : Size(sizeof(T)), Align(alignof(T)) {} - - template - struct accessor { - friend std::size_t SizeOf(const std::conditional_t, - pro::proxy_indirect_accessor>& self) noexcept { - const LayoutReflector& refl = pro::proxy_reflect(pro::access_proxy(self)); - return refl.Size; - } - - friend std::size_t AlignOf(const std::conditional_t, - pro::proxy_indirect_accessor>& self) noexcept { - const LayoutReflector& refl = pro::proxy_reflect(pro::access_proxy(self)); - return refl.Align; - } - }; - - std::size_t Size, Align; -}; - -struct LayoutAware : pro::facade_builder - ::add_direct_reflection - ::add_indirect_reflection - ::build {}; - -int main() { - int a = 123; - pro::proxy p = &a; - std::cout << SizeOf(p) << "\n"; // Prints sizeof(raw pointer) - std::cout << AlignOf(p) << "\n"; // Prints alignof(raw pointer) - std::cout << SizeOf(*p) << "\n"; // Prints sizeof(int) - std::cout << AlignOf(*p) << "\n"; // Prints alignof(int) - - p = pro::make_proxy(123); // SBO enabled - std::cout << SizeOf(p) << "\n"; // Prints sizeof(int) - std::cout << AlignOf(p) << "\n"; // Prints alignof(int) - std::cout << SizeOf(*p) << "\n"; // Prints sizeof(int) - std::cout << AlignOf(*p) << "\n"; // Prints alignof(int) - - p = pro::make_proxy>(); // SBO disabled - std::cout << SizeOf(p) << "\n"; // Prints sizeof(raw pointer) - std::cout << AlignOf(p) << "\n"; // Prints alignof(raw pointer) - std::cout << SizeOf(*p) << "\n"; // Prints "100" - std::cout << AlignOf(*p) << "\n"; // Prints "1" -} diff --git a/samples/basic_facade_builder/build.cpp b/samples/basic_facade_builder/build.cpp deleted file mode 100644 index 1df9c14f..00000000 --- a/samples/basic_facade_builder/build.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from build.md. - -#include - -#include "proxy.h" - -struct DefaultBase : pro::facade_builder - ::build {}; - -struct CopyableBase : pro::facade_builder - ::support_copy - ::build {}; - -struct TrivialBase : pro::facade_builder - ::support_copy - ::support_relocation - ::support_destruction - ::restrict_layout - ::build {}; - -int main() { - static_assert(!std::is_copy_constructible_v>); - static_assert(std::is_nothrow_move_constructible_v>); - static_assert(std::is_nothrow_destructible_v>); - - static_assert(std::is_copy_constructible_v>); - static_assert(std::is_nothrow_move_constructible_v>); - static_assert(std::is_nothrow_destructible_v>); - - static_assert(std::is_trivially_copy_constructible_v>); - static_assert(std::is_trivially_move_constructible_v>); - static_assert(std::is_trivially_destructible_v>); -} diff --git a/samples/basic_facade_builder/restrict_layout.cpp b/samples/basic_facade_builder/restrict_layout.cpp deleted file mode 100644 index c23b0484..00000000 --- a/samples/basic_facade_builder/restrict_layout.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from restrict_layout.md. - -#include -#include - -#include "proxy.h" - -struct DefaultFacade : pro::facade_builder::build {}; - -struct SmallFacade : pro::facade_builder - ::restrict_layout - ::build {}; - -int main() { - static_assert(sizeof(pro::proxy) > sizeof(pro::proxy)); - static_assert(pro::proxiable, DefaultFacade>); - static_assert(pro::proxiable, SmallFacade>); - static_assert(pro::proxiable, DefaultFacade>); - static_assert(!pro::proxiable, SmallFacade>); - static_assert(pro::inplace_proxiable_target, DefaultFacade>); - static_assert(!pro::inplace_proxiable_target, SmallFacade>); - static_assert(!pro::inplace_proxiable_target, DefaultFacade>); - static_assert(!pro::inplace_proxiable_target, SmallFacade>); - pro::proxy p1 = std::make_shared(123); - // pro::proxy p2 = std::make_shared(123); // Won't compile -} diff --git a/samples/basic_facade_builder/support_copy.cpp b/samples/basic_facade_builder/support_copy.cpp deleted file mode 100644 index 97e9904d..00000000 --- a/samples/basic_facade_builder/support_copy.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from support_copy.md. - -#include - -#include "proxy.h" - -struct Movable : pro::facade_builder::build {}; - -struct Copyable : pro::facade_builder - ::support_copy - ::build {}; - -int main() { - pro::proxy p1 = std::make_unique(123); - // pro::proxy p2 = std::make_unique(123); // Won't compile - pro::proxy p3 = std::make_shared(456); - // auto p4 = p1; // Won't compile - auto p5 = p3; -} diff --git a/samples/basic_facade_builder/support_destruction.cpp b/samples/basic_facade_builder/support_destruction.cpp deleted file mode 100644 index 2f591082..00000000 --- a/samples/basic_facade_builder/support_destruction.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from support_destruction.md. - -#include - -#include "proxy.h" - -struct Movable : pro::facade_builder::build {}; - -struct NonriviallyDestructible : pro::facade_builder - ::support_relocation - ::support_destruction - ::build {}; - -int main() { - static_assert(std::is_nothrow_destructible_v>); - static_assert(!std::is_nothrow_destructible_v>); -} diff --git a/samples/basic_facade_builder/support_format.cpp b/samples/basic_facade_builder/support_format.cpp deleted file mode 100644 index 0869bd6f..00000000 --- a/samples/basic_facade_builder/support_format.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from support_format.md. - -#include -#include - -#include "proxy.h" - -struct Formattable : pro::facade_builder - ::support_format - ::build {}; - -int main() { - pro::proxy p = pro::make_proxy(123); - std::cout << std::format("{}", *p) << "\n"; // Prints "123" - std::cout << std::format("{:*<6}", *p) << "\n"; // Prints "123***" -} diff --git a/samples/basic_facade_builder/support_relocation.cpp b/samples/basic_facade_builder/support_relocation.cpp deleted file mode 100644 index 4e46436c..00000000 --- a/samples/basic_facade_builder/support_relocation.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from support_relocation.md. - -#include - -#include "proxy.h" - -struct Movable : pro::facade_builder::build {}; - -struct Trivial : pro::facade_builder - ::support_copy - ::support_relocation - ::support_destruction - ::build {}; - -int main() { - pro::proxy p1 = std::make_unique(123); - // pro::proxy p2 = std::make_unique(456); // Won't compile - double v = 3.14; - pro::proxy p3 = &v; // Compiles because double* is trivial -} diff --git a/samples/basic_facade_builder/support_rtti.cpp b/samples/basic_facade_builder/support_rtti.cpp deleted file mode 100644 index 1d46efbe..00000000 --- a/samples/basic_facade_builder/support_rtti.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from support_rtti.md. - -#include - -#include "proxy.h" - -struct RttiAware : pro::facade_builder - ::support_rtti - ::support_direct_rtti - ::build {}; - -int main() { - int v = 123; - pro::proxy p = &v; - std::cout << proxy_typeid(p).name() << "\n"; // Prints "Pi" (assuming GCC) - std::cout << proxy_cast(p) << "\n"; // Prints the address of v - std::cout << proxy_typeid(*p).name() << "\n"; // Prints "i" (assuming GCC) - std::cout << proxy_cast(*p) << "\n"; // Prints "123" -} diff --git a/samples/basic_facade_builder/support_rtti/proxy_cast.cpp b/samples/basic_facade_builder/support_rtti/proxy_cast.cpp deleted file mode 100644 index 25ab381c..00000000 --- a/samples/basic_facade_builder/support_rtti/proxy_cast.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from proxy_cast.md. - -#include - -#include "proxy.h" - -struct RttiAware : pro::facade_builder - ::support_rtti - ::build {}; - -int main() { - int v = 123; - pro::proxy p; - try { - proxy_cast(*p); // Throws - } catch (const pro::bad_proxy_cast& e) { - std::cout << e.what() << "\n"; // Prints an explanatory string - } - p = &v; - std::cout << proxy_cast(*p) << "\n"; // Prints "123" - proxy_cast(*p) = 456; - std::cout << v << "\n"; // Prints "456" - try { - proxy_cast(*p); // Throws - } catch (const pro::bad_proxy_cast& e) { - std::cout << e.what() << "\n"; // Prints an explanatory string - } - int* ptr1 = proxy_cast(&*p); - std::cout << ptr1 << "\n"; // Prints an address - std::cout << &v << "\n"; // Prints the same address as above - double* ptr2 = proxy_cast(&*p); - std::cout << ptr2 << "\n"; // Prints "0" -} diff --git a/samples/basic_facade_builder/support_rtti/proxy_typeid.cpp b/samples/basic_facade_builder/support_rtti/proxy_typeid.cpp deleted file mode 100644 index 1d498206..00000000 --- a/samples/basic_facade_builder/support_rtti/proxy_typeid.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from proxy_typeid.md. - -#include - -#include "proxy.h" - -struct RttiAware : pro::facade_builder - ::support_rtti - ::build {}; - -int main() { - pro::proxy p; - std::cout << proxy_typeid(*p).name() << "\n"; // Prints "v" (assuming GCC) - p = pro::make_proxy(123); - std::cout << proxy_typeid(*p).name() << "\n"; // Prints "i" (assuming GCC) -} diff --git a/samples/basic_facade_builder/support_view.cpp b/samples/basic_facade_builder/support_view.cpp deleted file mode 100644 index c6216237..00000000 --- a/samples/basic_facade_builder/support_view.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from support_view.md. - -#include - -#include "proxy.h" - -struct RttiAware : pro::facade_builder - ::support_rtti - ::support_view - ::build {}; - -int main() { - pro::proxy p = pro::make_proxy(123); - pro::proxy_view pv = p; - proxy_cast(*pv) = 456; // Modifies the contained object of p - std::cout << proxy_cast(*pv) << "\n"; // Prints "456" - std::cout << proxy_cast(*p) << "\n"; // Prints "456" -} diff --git a/samples/basic_facade_builder/support_weak.cpp b/samples/basic_facade_builder/support_weak.cpp deleted file mode 100644 index 4f699098..00000000 --- a/samples/basic_facade_builder/support_weak.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from support_weak.md. - -#include - -#include "proxy.h" - -struct Formattable : pro::facade_builder - ::support_format - ::support_weak - ::build {}; - -int main() { - pro::proxy p1 = pro::make_proxy_shared(123); - pro::weak_proxy wp = p1; - pro::proxy 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/explicit_conversion_dispatch.cpp b/samples/explicit_conversion_dispatch.cpp deleted file mode 100644 index 68266639..00000000 --- a/samples/explicit_conversion_dispatch.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from explicit_conversion_dispatch.md. - -#include - -#include "proxy.h" - -struct IntConvertible : pro::facade_builder - ::add_convention - ::build {}; - -int main() { - pro::proxy p = pro::make_proxy(123); // p holds a short - std::cout << static_cast(*p) << "\n"; // Prints "123" -} diff --git a/samples/facade_aware_overload_t.cpp b/samples/facade_aware_overload_t.cpp deleted file mode 100644 index e916560b..00000000 --- a/samples/facade_aware_overload_t.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from facade_aware_overload_t.md. - -#include - -#include "proxy.h" - -template -using BinaryOverload = pro::proxy(const pro::proxy_indirect_accessor& rhs) const; - -template -pro::proxy operator+(const T& value, const pro::proxy_indirect_accessor& rhs) - requires(!std::is_same_v>) - { return pro::make_proxy(value + proxy_cast(rhs)); } - -struct Addable : pro::facade_builder - ::support_rtti - ::support_format - ::add_convention, pro::facade_aware_overload_t> - ::build {}; - -int main() { - pro::proxy p1 = pro::make_proxy(1); - pro::proxy p2 = pro::make_proxy(2); - pro::proxy p3 = *p1 + *p2; - std::cout << std::format("{}\n", *p3); // Prints "3" -} diff --git a/samples/implicit_conversion_dispatch.cpp b/samples/implicit_conversion_dispatch.cpp deleted file mode 100644 index e818ab68..00000000 --- a/samples/implicit_conversion_dispatch.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from implicit_conversion_dispatch.md. - -#include - -#include "proxy.h" - -struct Runnable : pro::facade_builder - ::add_convention, void()> - ::build {}; - -struct CopyableRunnable : pro::facade_builder - ::support_copy - ::add_facade - ::add_direct_convention() const&, pro::proxy() &&> - ::build {}; - -int main() { - pro::proxy p1 = pro::make_proxy( - [] { std::cout << "Lambda expression invoked\n"; }); - auto p2 = p1; // Copy construction - pro::proxy p3 = p2; // Implicit conversion via const reference of pro::proxy - std::cout << std::boolalpha << p2.has_value() << "\n"; // Prints "true" - // auto p4 = p3; // Won't compile because pro::proxy is not copy-constructible - pro::proxy p5 = std::move(p2); // Implicit conversion via rvalue reference of pro::proxy - std::cout << p2.has_value() << "\n"; // Prints "false" - (*p5)(); // Prints "Lambda expression invoked" -} diff --git a/samples/inplace_proxiable_target.cpp b/samples/inplace_proxiable_target.cpp deleted file mode 100644 index 7930c45c..00000000 --- a/samples/inplace_proxiable_target.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from inplace_proxiable_target.md. - -#include - -#include "proxy.h" - -// By default, the maximum pointer size defined by pro::facade_builder -// is 2 * sizeof(void*). This value can be overridden by `restrict_layout`. -struct Any : pro::facade_builder::build {}; - -int main() { - // sizeof(int) is usually not greater than sizeof(void*) for modern - // 32/64-bit compilers - static_assert(pro::inplace_proxiable_target); - - // sizeof(std::array) is usually greater than 2 * sizeof(void*) - static_assert(!pro::inplace_proxiable_target, Any>); -} diff --git a/samples/make_proxy.cpp b/samples/make_proxy.cpp deleted file mode 100644 index 7fd20c67..00000000 --- a/samples/make_proxy.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from make_proxy.md. - -#include -#include -#include - -#include "proxy.h" - -struct Printable : pro::facade_builder - ::add_convention, std::ostream&(std::ostream&) const> - ::build {}; - -int main() { - pro::proxy p1 = pro::make_proxy(true); // From bool - pro::proxy p2 = pro::make_proxy(123); // From int - pro::proxy p3 = pro::make_proxy(3.1415926); // From double - pro::proxy p4 = pro::make_proxy("lalala"); // From const char* - pro::proxy p5 = pro::make_proxy(5, 'x'); // From a in-place constructed string - std::cout << std::boolalpha << *p1 << "\n"; // Prints "true" - std::cout << *p2 << "\n"; // Prints "123" - std::cout << std::fixed << std::setprecision(10) << *p3 << "\n"; // Prints "3.1415926000" - std::cout << *p4 << "\n"; // Prints "lalala" - std::cout << *p5 << "\n"; // Prints "xxxxx" -} diff --git a/samples/make_proxy_inplace.cpp b/samples/make_proxy_inplace.cpp deleted file mode 100644 index 0f3d6b60..00000000 --- a/samples/make_proxy_inplace.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from make_proxy_inplace.md. - -#include - -#include "proxy.h" - -// By default, the maximum pointer size defined by pro::facade_builder -// is 2 * sizeof(void*). This value can be overridden by `restrict_layout`. -struct Any : pro::facade_builder::build {}; - -int main() { - // sizeof(int) is usually not greater than sizeof(void*) for modern - // 32/64-bit compilers - pro::proxy p1 = pro::make_proxy_inplace(123); - - // sizeof(std::array) is usually greater than 2 * sizeof(void*) - // pro::proxy p2 = pro::make_proxy_inplace>(); // Won't compile -} diff --git a/samples/make_proxy_shared.cpp b/samples/make_proxy_shared.cpp deleted file mode 100644 index 7fade471..00000000 --- a/samples/make_proxy_shared.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from make_proxy_shared.md. - -#include - -#include "proxy.h" - -struct RttiAware : pro::facade_builder - ::support_copy - ::support_rtti - ::support_weak - ::build {}; - -int main() { - pro::proxy p1 = pro::make_proxy_shared(123); - pro::weak_proxy p2 = p1; - pro::proxy p3 = p2.lock(); - std::cout << std::boolalpha << p3.has_value() << "\n"; // Prints "true" - std::cout << proxy_cast(*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 deleted file mode 100644 index bd359577..00000000 --- a/samples/make_proxy_view.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from make_proxy_view.md. - -#include -#include -#include - -#include "proxy.h" - -PRO_DEF_MEM_DISPATCH(MemAt, at); - -struct ResourceDictionary : pro::facade_builder - ::add_convention - ::build {}; - -int main() { - std::map dict; - dict[1] = "init"; - pro::proxy_view pv = pro::make_proxy_view(dict); - static_assert(std::is_same_vat(1)), std::string&>, "Non-const overload"); - static_assert(std::is_same_vat(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/msft_lib_proxy.cpp b/samples/msft_lib_proxy.cpp deleted file mode 100644 index 4bbb0d91..00000000 --- a/samples/msft_lib_proxy.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from msft_lib_proxy.md. - -#include - -#include "proxy.h" - -int main() { -#if defined(__msft_lib_proxy) && __msft_lib_proxy >= 202408L - puts("Compiled with library Proxy 3.0.0 or above."); -#else - puts("Cannot determine the version of library Proxy."); -#endif -} diff --git a/samples/operator_dispatch.cpp b/samples/operator_dispatch.cpp deleted file mode 100644 index 535c2391..00000000 --- a/samples/operator_dispatch.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from operator_dispatch.md. - -#include -#include -#include - -#include "proxy.h" - -struct Number : pro::facade_builder - ::add_convention, void(int)> - ::add_convention, std::ostream&(std::ostream&) const&> - ::build {}; - -int main() { - pro::proxy p1 = pro::make_proxy(std::numbers::pi); - *p1 *= 3; - std::cout << std::setprecision(10) << *p1 << "\n"; // Prints: 9.424777961 - - pro::proxy p2 = pro::make_proxy(10); - *p2 *= 5; - std::cout << *p2 << "\n"; // Prints: 50 -} diff --git a/samples/proxiable.cpp b/samples/proxiable.cpp deleted file mode 100644 index f7309129..00000000 --- a/samples/proxiable.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from proxiable.md. - -#include -#include - -#include "proxy.h" - -PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); - -struct Stringable : pro::facade_builder - ::add_convention - ::build {}; - -int main() { - static_assert(pro::proxiable); - static_assert(pro::proxiable, Stringable>); - static_assert(!pro::proxiable*, Stringable>); -} diff --git a/samples/proxiable_target.cpp b/samples/proxiable_target.cpp deleted file mode 100644 index 0d89e7e7..00000000 --- a/samples/proxiable_target.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// 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, void()> - ::build {}; - -int main() { - auto fun = [] {}; - static_assert(pro::proxiable_target); - static_assert(!pro::proxiable_target); -} diff --git a/samples/proxy.cpp b/samples/proxy.cpp deleted file mode 100644 index 01521c6e..00000000 --- a/samples/proxy.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from proxy.md. - -#include -#include -#include -#include -#include - -#include "proxy.h" - -PRO_DEF_MEM_DISPATCH(MemAt, at); - -struct Dictionary : pro::facade_builder - ::add_convention - ::build {}; - -// This is a function, rather than a function template -void PrintDictionary(pro::proxy dictionary) { - std::cout << dictionary->at(1) << "\n"; -} - -int main() { - static std::map container1{{1, "hello"}}; - auto container2 = std::make_shared>(); - container2->push_back("hello"); - container2->push_back("world"); - PrintDictionary(&container1); // Prints "hello" - PrintDictionary(container2); // Prints "world" -} diff --git a/samples/proxy/constructor.cpp b/samples/proxy/constructor.cpp deleted file mode 100644 index 47411034..00000000 --- a/samples/proxy/constructor.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from constructor.md. - -#include -#include -#include - -#include "proxy.h" - -PRO_DEF_MEM_DISPATCH(MemSize, size); -PRO_DEF_MEM_DISPATCH(MemClear, clear); - -struct BasicContainer : pro::facade_builder - ::add_convention - ::add_convention - ::support_copy - ::build {}; - -int main() { - std::vector v{1, 2, 3}; - - pro::proxy p0; - std::cout << std::boolalpha << p0.has_value() << "\n"; // Prints "false" - - // Construct a proxy with a raw pointer - pro::proxy p1 = &v; - std::cout << p1.has_value() << ", " << p1->size() << "\n"; // Prints "true,3" - - // Construct a proxy with a smart pointer - pro::proxy p2 = std::make_shared>(10); - std::cout << p2.has_value() << ", " << p2->size() << "\n"; // Prints "true,10" - - // Copy construction - pro::proxy p3 = p2; - std::cout << p3.has_value() << ", " << p3->size() << "\n"; // Prints "true,10" - - // Move construction - pro::proxy p4 = std::move(p3); - std::cout << p4.has_value() << ", " << p4->size() << "\n"; // Prints "true,10" - - // p3 no longer contains a value - std::cout << p3.has_value() << "\n"; // Prints "false" - - // p2 and p4 shares the same object of std::deque - p2->clear(); - std::cout << p4.has_value() << ", " << p4->size() << "\n"; // Prints "true,0" -} diff --git a/samples/proxy/destructor.cpp b/samples/proxy/destructor.cpp deleted file mode 100644 index bf104c35..00000000 --- a/samples/proxy/destructor.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from destructor.md. - -#include - -#include "proxy.h" - -struct AnyMovable : pro::facade_builder::build {}; - -struct Foo { - ~Foo() { puts("Destroy Foo"); } -}; - -int main() { - pro::proxy p = pro::make_proxy(); -} // The destructor of `Foo` is called when `p` is destroyed diff --git a/samples/proxy/emplace.cpp b/samples/proxy/emplace.cpp deleted file mode 100644 index aa533b84..00000000 --- a/samples/proxy/emplace.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from emplace.md. - -#include -#include -#include - -#include "proxy.h" - -struct AnyCopyable : pro::facade_builder - ::support_copy - ::build {}; - -struct Foo { - ~Foo() { puts("Destroy Foo"); } - - int payload[10000]; -}; - -int main() { - static std::pmr::unsynchronized_pool_resource my_memory_pool; - - std::pmr::polymorphic_allocator<> alloc{&my_memory_pool}; - auto deleter = [alloc](auto* ptr) mutable { alloc.delete_object(ptr); }; - - pro::proxy p0; - p0.emplace>(alloc.new_object(), deleter); - pro::proxy p1 = p0; // `Foo` is not copied. Only the reference count is increased. -} // The destructor of `Foo` is called once when both `p0` and `p1` are destroyed diff --git a/samples/proxy/friend_operator_equality.cpp b/samples/proxy/friend_operator_equality.cpp deleted file mode 100644 index 1a050654..00000000 --- a/samples/proxy/friend_operator_equality.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from friend_operator_equality.md. - -#include - -#include "proxy.h" - -struct AnyMovable : pro::facade_builder::build {}; - -int main() { - pro::proxy p; - std::cout << std::boolalpha << (p == nullptr) << "\n"; // Prints "true" - std::cout << (p != nullptr) << "\n"; // Prints "false" - p = std::make_unique(123); - std::cout << (p == nullptr) << "\n"; // Prints "false" - std::cout << (p != nullptr) << "\n"; // Prints "true" -} diff --git a/samples/proxy/friend_swap.cpp b/samples/proxy/friend_swap.cpp deleted file mode 100644 index 88bc17b1..00000000 --- a/samples/proxy/friend_swap.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from friend_swap.md. - -#include -#include -#include - -#include "proxy.h" - -PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); - -struct Stringable : pro::facade_builder - ::add_convention - ::build {}; - -int main() { - pro::proxy p0 = pro::make_proxy(123); - pro::proxy p1 = pro::make_proxy(std::numbers::pi); - std::cout << ToString(*p0) << "\n"; // Prints "10" - std::cout << ToString(*p1) << "\n"; // Prints "3.14..." - std::ranges::swap(p0, p1); // finds the hidden friend - std::cout << ToString(*p0) << "\n"; // Prints "3.14..." - std::cout << ToString(*p1) << "\n"; // Prints "10" -} diff --git a/samples/proxy/indirection.cpp b/samples/proxy/indirection.cpp deleted file mode 100644 index d5b63946..00000000 --- a/samples/proxy/indirection.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from indirection.md. - -#include -#include -#include - -#include "proxy.h" - -PRO_DEF_MEM_DISPATCH(MemSize, size); - -struct BasicContainer : pro::facade_builder - ::add_convention - ::build {}; - -PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); - -struct Stringable : pro::facade_builder - ::add_convention - ::build {}; - -int main() { - std::vector v(10); - pro::proxy p0 = &v; - std::cout << p0->size() << "\n"; // Prints "10" - std::cout << (*p0).size() << "\n"; // Prints "10" - - pro::proxy p1 = pro::make_proxy(123); - std::cout << ToString(*p1) << "\n"; // Prints "123" -} diff --git a/samples/proxy/operator_bool.cpp b/samples/proxy/operator_bool.cpp deleted file mode 100644 index 1e2ebf63..00000000 --- a/samples/proxy/operator_bool.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from operator_bool.md. - -#include - -#include "proxy.h" - -struct AnyMovable : pro::facade_builder::build {}; - -int main() { - pro::proxy p; - std::cout << std::boolalpha << p.has_value() << "\n"; // Prints "false" - p = pro::make_proxy(123); - std::cout << p.has_value() << "\n"; // Prints "true" - p = nullptr; - std::cout << static_cast(p) << "\n"; // Prints "false" -} diff --git a/samples/proxy/reset.cpp b/samples/proxy/reset.cpp deleted file mode 100644 index f4039534..00000000 --- a/samples/proxy/reset.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from reset.md. - -#include - -#include "proxy.h" - -struct AnyMovable : pro::facade_builder::build {}; - -int main() { - pro::proxy p = pro::make_proxy(123); - std::cout << std::boolalpha << p.has_value() << "\n"; // Prints "true" - p.reset(); - std::cout << p.has_value() << "\n"; // Prints "false" -} diff --git a/samples/proxy_invoke.cpp b/samples/proxy_invoke.cpp deleted file mode 100644 index 9da35ae0..00000000 --- a/samples/proxy_invoke.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from proxy_invoke.md. - -#include -#include - -#include "proxy.h" - -PRO_DEF_FREE_DISPATCH(FreeToString, std::to_string, ToString); - -struct Stringable : pro::facade_builder - ::add_convention - ::build {}; - -int main() { - int a = 123; - pro::proxy p = &a; - std::cout << ToString(*p) << "\n"; // Invokes with accessor, prints: "123" - std::cout << pro::proxy_invoke(p) << "\n"; // Invokes with proxy_invoke, also prints: "123" -} diff --git a/samples/proxy_reflect.cpp b/samples/proxy_reflect.cpp deleted file mode 100644 index 8e03450c..00000000 --- a/samples/proxy_reflect.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from proxy_reflect.md. - -#include -#include -#include - -#include "proxy.h" - -class CopyabilityReflector { - public: - template - constexpr explicit CopyabilityReflector(std::in_place_type_t) - : copyable_(std::is_copy_constructible_v) {} - - template - struct accessor { - bool IsCopyable() const noexcept { - const CopyabilityReflector& self = pro::proxy_reflect(pro::access_proxy(*this)); - return self.copyable_; - } - }; - - private: - bool copyable_; -}; - -struct CopyabilityAware : pro::facade_builder - ::add_direct_reflection - ::build {}; - -int main() { - pro::proxy p1 = std::make_unique(); - std::cout << std::boolalpha << p1.IsCopyable() << "\n"; // Prints "false" - - pro::proxy p2 = std::make_shared(); - std::cout << p2.IsCopyable() << "\n"; // Prints "true" -} diff --git a/samples/proxy_view.cpp b/samples/proxy_view.cpp deleted file mode 100644 index 41f53182..00000000 --- a/samples/proxy_view.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from proxy_view.md. - -#include - -#include "proxy.h" - -template -struct FMap : pro::facade_builder - ::add_convention, V&(const K& key)> - ::build {}; - -int main() { - std::map v; - pro::proxy_view> p = &v; - (*p)[1] = 123; - printf("%d\n", v.at(1)); // Prints "123" -} diff --git a/samples/weak_dispatch.cpp b/samples/weak_dispatch.cpp deleted file mode 100644 index c57d6e61..00000000 --- a/samples/weak_dispatch.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from weak_dispatch.md. - -#include -#include -#include - -#include "proxy.h" - -PRO_DEF_MEM_DISPATCH(MemAt, at); - -struct WeakDictionary : pro::facade_builder - ::add_convention, std::string(int index) const> - ::build {}; - -int main() { - std::vector v{"hello", "world"}; - pro::proxy p1 = &v; - std::cout << p1->at(1) << "\n"; // Prints "world" - pro::proxy p2 = pro::make_proxy(123); - try { - p2->at(1); - } catch (const pro::not_implemented& e) { - std::cout << e.what() << "\n"; // Prints an explanatory string - } -} diff --git a/samples/weak_proxy.cpp b/samples/weak_proxy.cpp deleted file mode 100644 index 632ee8d3..00000000 --- a/samples/weak_proxy.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// This file contains example code from weak_proxy.md. - -#include - -#include "proxy.h" - -struct Formattable : pro::facade_builder - ::support_format - ::build {}; - -int main() { - std::shared_ptr val = std::make_shared(123); - pro::weak_proxy wp = std::weak_ptr{val}; - pro::proxy 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" -} diff --git a/tests/freestanding/proxy_freestanding_tests.cpp b/tests/freestanding/proxy_freestanding_tests.cpp index fc584e55..9659d19c 100644 --- a/tests/freestanding/proxy_freestanding_tests.cpp +++ b/tests/freestanding/proxy_freestanding_tests.cpp @@ -2,7 +2,7 @@ #error "This file shall be compiled targeting a freestanding environment." #endif // __STDC_HOSTED__ -#include "proxy.h" +#include constexpr unsigned DefaultHash = -1; unsigned GetHash(int v) { return static_cast(v + 3) * 31; } diff --git a/tests/proxy_creation_tests.cpp b/tests/proxy_creation_tests.cpp index ad78f3f2..afb331f6 100644 --- a/tests/proxy_creation_tests.cpp +++ b/tests/proxy_creation_tests.cpp @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#include "utils.h" #include #include -#include "proxy.h" -#include "utils.h" +#include namespace proxy_creation_tests_details { diff --git a/tests/proxy_dispatch_tests.cpp b/tests/proxy_dispatch_tests.cpp index aa08a6d0..373e3d31 100644 --- a/tests/proxy_dispatch_tests.cpp +++ b/tests/proxy_dispatch_tests.cpp @@ -8,7 +8,7 @@ #pragma warning(push) #pragma warning(disable: 4834) // False alarm from MSVC: warning C4834: discarding return value of function with [[nodiscard]] attribute #endif // defined(_MSC_VER) && !defined(__clang__) -#include "proxy.h" +#include #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(pop) #endif // defined(_MSC_VER) && !defined(__clang__) diff --git a/tests/proxy_format_tests.cpp b/tests/proxy_format_tests.cpp index c5beab21..432728c6 100644 --- a/tests/proxy_format_tests.cpp +++ b/tests/proxy_format_tests.cpp @@ -2,7 +2,7 @@ // Licensed under the MIT License. #include -#include "proxy.h" +#include namespace proxy_format_tests_details { diff --git a/tests/proxy_integration_tests.cpp b/tests/proxy_integration_tests.cpp index a85f162e..a0a76e8a 100644 --- a/tests/proxy_integration_tests.cpp +++ b/tests/proxy_integration_tests.cpp @@ -6,10 +6,10 @@ #include #include #include +#include #include #include #include -#include "proxy.h" namespace proxy_integration_tests_details { diff --git a/tests/proxy_invocation_tests.cpp b/tests/proxy_invocation_tests.cpp index 3610138e..cb479963 100644 --- a/tests/proxy_invocation_tests.cpp +++ b/tests/proxy_invocation_tests.cpp @@ -17,7 +17,7 @@ #pragma warning(push) #pragma warning(disable: 4702) // False alarm from MSVC: warning C4702: unreachable code #endif // defined(_MSC_VER) && !defined(__clang__) -#include "proxy.h" +#include #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(pop) #endif // defined(_MSC_VER) && !defined(__clang__) diff --git a/tests/proxy_lifetime_tests.cpp b/tests/proxy_lifetime_tests.cpp index feb447b0..707ff207 100644 --- a/tests/proxy_lifetime_tests.cpp +++ b/tests/proxy_lifetime_tests.cpp @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -#include -#include "proxy.h" #include "utils.h" +#include +#include namespace proxy_lifetime_tests_details { diff --git a/tests/proxy_reflection_tests.cpp b/tests/proxy_reflection_tests.cpp index e4c157a0..0571319b 100644 --- a/tests/proxy_reflection_tests.cpp +++ b/tests/proxy_reflection_tests.cpp @@ -1,11 +1,11 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#include "utils.h" #include #include +#include #include -#include "proxy.h" -#include "utils.h" namespace proxy_reflection_tests_details { diff --git a/tests/proxy_regression_tests.cpp b/tests/proxy_regression_tests.cpp index 84ca515a..aabfda53 100644 --- a/tests/proxy_regression_tests.cpp +++ b/tests/proxy_regression_tests.cpp @@ -2,8 +2,8 @@ // Licensed under the MIT License. #include +#include #include -#include "proxy.h" namespace proxy_regression_tests_details { diff --git a/tests/proxy_rtti_tests.cpp b/tests/proxy_rtti_tests.cpp index 42b0b6fd..4c83a6fb 100644 --- a/tests/proxy_rtti_tests.cpp +++ b/tests/proxy_rtti_tests.cpp @@ -2,8 +2,8 @@ // Licensed under the MIT License. #include +#include #include -#include "proxy.h" namespace proxy_rtti_tests_details { diff --git a/tests/proxy_traits_tests.cpp b/tests/proxy_traits_tests.cpp index 55259c5b..77004ec7 100644 --- a/tests/proxy_traits_tests.cpp +++ b/tests/proxy_traits_tests.cpp @@ -1,11 +1,11 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#include "utils.h" #include +#include #include #include -#include "proxy.h" -#include "utils.h" namespace proxy_traits_tests_details { diff --git a/tests/proxy_view_tests.cpp b/tests/proxy_view_tests.cpp index 7788007b..5835d549 100644 --- a/tests/proxy_view_tests.cpp +++ b/tests/proxy_view_tests.cpp @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -#include -#include "proxy.h" #include "utils.h" +#include +#include namespace proxy_view_tests_details { diff --git a/tests/utils.h b/tests/utils.h index 1ae4ba00..cdda99d9 100644 --- a/tests/utils.h +++ b/tests/utils.h @@ -4,6 +4,7 @@ #ifndef _MSFT_PROXY_TEST_UTILS_ #define _MSFT_PROXY_TEST_UTILS_ +#include #include #include diff --git a/tools/extract_example_code_from_docs.py b/tools/extract_example_code_from_docs.py new file mode 100644 index 00000000..69730ac6 --- /dev/null +++ b/tools/extract_example_code_from_docs.py @@ -0,0 +1,42 @@ +import os +import re +import sys + +def extract_cpp_code(md_path, cpp_path): + with open(md_path, 'r', encoding='utf-8') as f: + content = f.read() + + pattern = r'## Example\r?\n\r?\n```cpp\r?\n(.*?)\r?\n```' + code_blocks = re.findall(pattern, content, re.DOTALL) + + if len(code_blocks) == 0: + return # No match, skip + elif len(code_blocks) > 1: + raise ValueError(f"File '{md_path}' contains more than one '## Example' C++ code block.") + + cpp_code = code_blocks[0] + header = f"// This file was auto-generated from: {md_path}\n// Do not edit this file manually.\n\n" + + with open(cpp_path, 'w', encoding='utf-8') as out: + out.write(header) + out.write(cpp_code) + +def main(): + if len(sys.argv) != 3: + print("Usage: python extract_example_code_from_docs.py ") + sys.exit(1) + + input_dir = sys.argv[1] + output_dir = sys.argv[2] + + for root, _, files in os.walk(input_dir): + for file in files: + if file.endswith('.md'): + md_path = os.path.join(root, file) + rel_path = os.path.relpath(md_path, input_dir) + rel_base = os.path.splitext(rel_path)[0].replace(os.sep, '_') + cpp_path = os.path.join(output_dir, f"example_{rel_base}.cpp") + extract_cpp_code(md_path, cpp_path) + +if __name__ == '__main__': + main()