/* * MIT License * * Copyright (c) 2023 igozdev * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include namespace pc { namespace detail { template struct storer { inline static T value; }; template struct holder { }; } template struct accessor { inline static const auto value = detail::storer::value = V; }; enum class modifier { const_ = 1 << 0, volatile_ = 1 << 1, lvalue = 1 << 2, rvalue = 1 << 3, }; constexpr modifier operator|(modifier lhs, modifier rhs) { return static_cast(static_cast>(lhs) | static_cast>(rhs)); } template struct modified { using type = T; constexpr static modifier mods = Mods; }; template concept Modified = std::is_same_v>; template auto public_cast(ClassT& t) requires std::is_function_v { return [&t](detail::holder) { return [&t](TArgs... args) { return (t.*detail::storer::value)(args...); }; }(detail::holder{}); } template auto& public_cast(ClassT& t) requires (!std::is_function_v && !Modified) { return t.*(detail::storer::value); } template auto& public_cast() { return *detail::storer::value; } template auto publicize() requires (!Modified) { return detail::storer::value; } template auto publicize_static() { return detail::storer::value; } template auto public_cast(const ClassT& t) requires (T::mods == modifier::const_) { return [&t](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) const; return [&t](TArgs... args) { return (t.*detail::storer::value)(args...); }; }(detail::holder{}); } template auto public_cast(volatile ClassT& t) requires (T::mods == modifier::volatile_) { return [&t](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) volatile; return [&t](TArgs... args) { return (t.*detail::storer::value)(args...); }; }(detail::holder{}); } template auto public_cast(ClassT& t) requires (T::mods == modifier::lvalue) { return [&t](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) &; return [&t](TArgs... args) { return (t.*detail::storer::value)(args...); }; }(detail::holder{}); } template auto public_cast(ClassT&& t) requires (T::mods == modifier::rvalue) { return [&t](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) &&; return [&t](TArgs... args) { return (std::move(t).*detail::storer::value)(args...); }; }(detail::holder{}); } template auto public_cast(const volatile ClassT& t) requires (T::mods == (modifier::const_ | modifier::volatile_)) { return [&t](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) const volatile; return [&t](TArgs... args) { return (t.*detail::storer::value)(args...); }; }(detail::holder{}); } template auto public_cast(const ClassT& t) requires (T::mods == (modifier::const_ | modifier::lvalue)) { return [&t](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) const &; return [&t](TArgs... args) { return (t.*detail::storer::value)(args...); }; }(detail::holder{}); } template auto public_cast(const ClassT&& t) requires (T::mods == (modifier::const_ | modifier::rvalue)) { return [&t](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) const &&; return [&t](TArgs... args) { return (std::move(t).*detail::storer::value)(args...); }; }(detail::holder{}); } template auto public_cast(volatile ClassT& t) requires (T::mods == (modifier::volatile_ | modifier::lvalue)) { return [&t](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) volatile &; return [&t](TArgs... args) { return (t.*detail::storer::value)(args...); }; }(detail::holder{}); } template auto public_cast(volatile ClassT&& t) requires (T::mods == (modifier::volatile_ | modifier::rvalue)) { return [&t](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) volatile &&; return [&t](TArgs... args) { return (std::move(t).*detail::storer::value)(args...); }; }(detail::holder{}); } template auto public_cast(const volatile ClassT& t) requires (T::mods == (modifier::const_ | modifier::volatile_ | modifier::lvalue)) { return [&t](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) const volatile &; return [&t](TArgs... args) { return (t.*detail::storer::value)(args...); }; }(detail::holder{}); } template auto public_cast(const volatile ClassT&& t) requires (T::mods == (modifier::const_ | modifier::volatile_ | modifier::rvalue)) { return [&t](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) const volatile &&; return [&t](TArgs... args) { return (std::move(t).*detail::storer::value)(args...); }; }(detail::holder{}); } template auto publicize() requires (T::mods == modifier::const_) { return [](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) const; return detail::storer::value; }(detail::holder{}); } template auto publicize() requires (T::mods == modifier::volatile_) { return [](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) volatile; return detail::storer::value; }(detail::holder{}); } template auto publicize() requires (T::mods == modifier::lvalue) { return [](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) &; return detail::storer::value; }(detail::holder{}); } template auto publicize() requires (T::mods == modifier::rvalue) { return [](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) &&; return detail::storer::value; }(detail::holder{}); } template auto publicize() requires (T::mods == (modifier::const_ | modifier::volatile_)) { return [](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) const volatile; return detail::storer::value; }(detail::holder{}); } template auto publicize() requires (T::mods == (modifier::const_ | modifier::lvalue)) { return [](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) const &; return detail::storer::value; }(detail::holder{}); } template auto publicize() requires (T::mods == (modifier::const_ | modifier::rvalue)) { return [](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) const &&; return detail::storer::value; }(detail::holder{}); } template auto publicize() requires (T::mods == (modifier::volatile_ | modifier::lvalue)) { return [](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) volatile &; return detail::storer::value; }(detail::holder{}); } template auto publicize() requires (T::mods == (modifier::volatile_ | modifier::rvalue)) { return [](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) volatile &&; return detail::storer::value; }(detail::holder{}); } template auto publicize() requires (T::mods == (modifier::const_ | modifier::volatile_ | modifier::lvalue)) { return [](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) const volatile &; return detail::storer::value; }(detail::holder{}); } template auto publicize() requires (T::mods == (modifier::const_ | modifier::volatile_ | modifier::rvalue)) { return [](detail::holder) { using ptr_type = TR(ClassT::*)(TArgs...) const volatile &&; return detail::storer::value; }(detail::holder{}); } }