/* * Copyright (C) 2018 ScyllaDB */ /* * This file is part of Scylla. * * Scylla is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Scylla is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scylla. If not, see . */ #pragma once namespace imr { namespace methods { template typename Method> struct trivial_method { template static void run(Args&&...) noexcept { } }; template typename Method, typename T> using has_trivial_method = std::is_base_of, Method>; namespace internal { template typename Method, typename...> struct generate_method : trivial_method { }; template typename Method, typename Structure, typename... Tags, typename... Types> struct generate_method...> { template static void run(uint8_t* ptr, const Context& context, Args&&... args) noexcept { auto view = Structure::make_view(ptr, context); meta::for_each...>([&] (auto member_type) { using member = std::remove_pointer_t; auto member_ptr = ptr + view.template offset_of(); Method::run(member_ptr, context.template context_for(member_ptr), std::forward(args)...); }); } }; template typename Method, typename Tag, typename Type> struct generate_method> { template static void run(uint8_t* ptr, const Context& context, Args&&... args) noexcept { if (context.template is_present()) { Method::run(ptr, context.template context_for(ptr), std::forward(args)...); } } }; template typename Method, typename Tag, typename... Members> struct generate_method> { template static void run(uint8_t* ptr, const Context& context, Args&&... args) noexcept { auto view = variant::make_view(ptr, context); view.visit_type([&] (auto alternative_type) { using member = std::remove_pointer_t; Method::run(ptr, context.template context_for(ptr), std::forward(args)...); }, context); } }; template typename Method> struct member_has_trivial_method { template struct type; }; template typename Method> template struct member_has_trivial_method::type> : has_trivial_method { }; template typename Method, typename T> struct get_method; template typename Method, typename... Members> struct get_method> : std::conditional_t::template type, Members...>, trivial_method, generate_method, Members...>> { }; template typename Method, typename Tag, typename Type> struct get_method> : std::conditional_t::value, trivial_method, generate_method>> { }; template typename Method, typename Tag, typename... Members> struct get_method> : std::conditional_t::template type, Members...>, trivial_method, generate_method>> { }; template typename Method, typename Tag, typename Type> struct get_method> : std::conditional_t::value, trivial_method, Method> { }; } template struct destructor : trivial_method { }; using trivial_destructor = trivial_method; template using is_trivially_destructible = has_trivial_method; template struct destructor> : internal::get_method> { }; template struct destructor> : internal::get_method> { }; template struct destructor> : internal::get_method> { }; template void destroy(uint8_t* ptr, const Context& context = no_context) { destructor::run(ptr, context); } template struct mover : trivial_method { }; using trivial_mover = trivial_method; template using is_trivially_movable = has_trivial_method; template struct mover> : internal::get_method> { }; template struct mover> : internal::get_method> { }; template struct mover> : internal::get_method> { }; template void move(uint8_t* ptr, const Context& context = no_context) { mover::run(ptr, context); } } }