Created
March 1, 2026 23:56
-
-
Save unrays/cfd820e12fe69fa552ede9fb8930bb84 to your computer and use it in GitHub Desktop.
Unfinished C++ mini-framework for type-safe JSON construction using CRTP, operator overloading, and generic lambdas.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Copyright (c) March 2026 Félix-Olivier Dumas. All rights reserved. | |
| // Licensed under the terms described in the LICENSE file | |
| template<template<typename> class Res, template<typename> class Dis> | |
| struct JsonBuildingPair { | |
| template<typename T> | |
| using Resolver = Res<T>; | |
| template<typename T> | |
| using Dispatcher = Dis<T>; | |
| }; | |
| /********************************************************/ | |
| struct sentinel_t {}; | |
| inline constexpr sentinel_t sentinel{}; | |
| template<typename> | |
| concept requires_derived = true; | |
| struct parentheses; | |
| struct subscript; | |
| /***/ | |
| template<typename Operator, auto Behavior, typename CRTP_Context = void> | |
| struct operator_wrapper; | |
| template<auto Behavior> | |
| struct operator_wrapper<parentheses, Behavior> { | |
| template<typename... Args> | |
| auto operator()(Args&&... args) { | |
| return Behavior(std::forward<Args>(args)...); | |
| } | |
| }; | |
| template<auto Behavior, typename CRTP_Context> | |
| struct operator_wrapper<parentheses, Behavior, CRTP_Context> { | |
| template<typename... Args> | |
| auto operator()(Args&&... args) { | |
| return Behavior( | |
| std::forward<Args>(args)..., | |
| static_cast<CRTP_Context&>(*this) | |
| ); | |
| } | |
| }; | |
| /**/ | |
| template<auto Behavior> | |
| struct operator_wrapper<subscript, Behavior> { | |
| template<typename S = sentinel_t> | |
| auto operator[](S&&) { return Behavior(); } | |
| template<typename... Args> | |
| auto operator[](Args&&... args) { | |
| return Behavior(std::forward<Args>(args)...); | |
| } | |
| }; | |
| template<auto Behavior, typename CRTP_Context> | |
| struct operator_wrapper<subscript, Behavior, CRTP_Context> { | |
| template<typename S = sentinel_t> | |
| auto operator[](S&&) { return Behavior(static_cast<CRTP_Context&>(*this)); } | |
| template<typename... Args> | |
| auto operator[](Args&&... args) { | |
| return Behavior( | |
| std::forward<Args>(args)..., | |
| static_cast<CRTP_Context&>(*this) | |
| ); | |
| } | |
| }; | |
| /*********************************************************************/ | |
| struct JsonBuilderResolverTag {}; | |
| struct JsonBuilderDispatcherTag {}; | |
| /*********************************************************************/ | |
| template<typename OperatorTag, auto Behavior, typename CrtpContext> | |
| struct JsonBuilderOperatorBase : operator_wrapper<OperatorTag, Behavior, CrtpContext> {}; | |
| /*********************************************************************/ | |
| constexpr auto NumberDispatcherBehavior = | |
| []<typename CrtpContext>(auto val, CrtpContext&& context) { | |
| return context; | |
| }; | |
| template<typename CrtpContext> | |
| struct JsonBuilderNumberDispatcher : JsonBuilderDispatcherTag, | |
| public JsonBuilderOperatorBase<parentheses, NumberDispatcherBehavior, CrtpContext> | |
| { | |
| using Base = JsonBuilderOperatorBase<parentheses, NumberDispatcherBehavior, CrtpContext>; | |
| auto operator()(auto val) -> decltype(auto) { return Base::operator()(val); } | |
| }; | |
| /*********************************************************************/ | |
| constexpr auto NumberResolverBehavior = | |
| []<typename CrtpContext>(CrtpContext&& context) { | |
| return JsonBuilderNumberDispatcher<CrtpContext>{}; | |
| }; | |
| template<typename CrtpContext> | |
| struct JsonBuilderNumberResolver : JsonBuilderResolverTag, | |
| public JsonBuilderOperatorBase<subscript, NumberResolverBehavior, CrtpContext> | |
| { | |
| using Base = JsonBuilderOperatorBase<subscript, NumberResolverBehavior, CrtpContext>; | |
| auto operator[](JSON_TAG_NUMBER) -> decltype(auto) { return Base::operator[](sentinel); } | |
| }; | |
| /*********************************************************************/ | |
| constexpr auto TableResolverBehavior = | |
| []<typename CrtpContext>(CrtpContext&& context) { | |
| std::cout << typeid(CrtpContext).name() << "\n"; | |
| std::cout << context.a << "\n"; | |
| return ChainResolverA{}; | |
| }; | |
| template<typename CrtpContext> | |
| struct JsonBuilderTableResolver : JsonBuilderResolverTag, | |
| public JsonBuilderOperatorBase<subscript, TableResolverBehavior, CrtpContext> | |
| { | |
| using Base = JsonBuilderOperatorBase<subscript, TableResolverBehavior, CrtpContext>; | |
| auto operator[](JSON_TAG_TABLE) -> decltype(auto) { return Base::operator[](sentinel); } | |
| }; | |
| /*********************************************************************/ | |
| template<template<typename> class... Resolvers> | |
| struct JsonBuilderProxy2 : Resolvers<JsonBuilderProxy2<Resolvers...>>... { | |
| using Resolvers<JsonBuilderProxy2<Resolvers...>>::operator[]...; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment