From 84921fffa7aa6efd80f694ec295d4562c326fabc Mon Sep 17 00:00:00 2001 From: Brett Laptop Date: Wed, 23 Apr 2025 15:04:37 -0400 Subject: [PATCH] tuples! --- CMakeLists.txt | 2 +- include/blt/meta/function.h | 152 +++++++++++++++++++++++++++++++ include/blt/meta/passthrough.h | 31 +++++++ include/blt/meta/tuple_filters.h | 80 ++++++++++++++++ include/blt/std/variant.h | 65 ++++++------- tests/variant_tests.cpp | 24 ++--- 6 files changed, 306 insertions(+), 48 deletions(-) create mode 100644 include/blt/meta/function.h create mode 100644 include/blt/meta/passthrough.h create mode 100644 include/blt/meta/tuple_filters.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c812ac..1a2601a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) include(cmake/color.cmake) -set(BLT_VERSION 5.4.8) +set(BLT_VERSION 5.4.9) set(BLT_TARGET BLT) diff --git a/include/blt/meta/function.h b/include/blt/meta/function.h new file mode 100644 index 0000000..a64ebaa --- /dev/null +++ b/include/blt/meta/function.h @@ -0,0 +1,152 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see . + */ + +#ifndef BLT_META_FUNCTION_H +#define BLT_META_FUNCTION_H + +#include +#include + +namespace blt::meta +{ + struct std_function_tag + {}; + + struct function_ptr_tag + {}; + + struct lambda_tag + {}; + + struct member_function_ptr_tag + {}; + + template + struct function_like; + + template + struct function_like> + { + using return_type = Return; + using args_tuple = std::tuple; + using tag = std_function_tag; + }; + + template + struct function_like + { + using return_type = Return; + using args_tuple = std::tuple; + using tag = function_ptr_tag; + }; + + template + struct function_like + { + using return_type = Return; + using args_tuple = std::tuple; + using tag = function_ptr_tag; + }; + + template + struct function_like + { + using return_type = Return; + using args_tuple = std::tuple; + using tag = member_function_ptr_tag; + using class_type = Class; + }; + + template + struct function_like + { + using return_type = Return; + using args_tuple = std::tuple; + using tag = member_function_ptr_tag; + using class_type = Class; + }; + + template + struct function_like + { + using return_type = Return; + using args_tuple = std::tuple; + using tag = member_function_ptr_tag; + using class_type = Class; + }; + + template + struct function_like + { + using return_type = Return; + using args_tuple = std::tuple; + using tag = member_function_ptr_tag; + using class_type = Class; + }; + + template + struct function_like + { + private: + template + struct lambda_traits + {}; + + template + struct lambda_traits + { + using return_type = Return; + using args_tuple = std::tuple; + using class_type = Class; + }; + + template + struct lambda_traits + { + using return_type = Return; + using args_tuple = std::tuple; + using class_type = Class; + }; + + template + struct lambda_traits + { + using return_type = Return; + using args_tuple = std::tuple; + using class_type = Class; + }; + + template + struct lambda_traits + { + using return_type = Return; + using args_tuple = std::tuple; + using class_type = Class; + }; + + using lambda_trait = lambda_traits; + + public: + using tag_type = lambda_tag; + using return_type = typename lambda_trait::return_type; + using args_tuple = typename lambda_trait::args_tuple; + using class_type = typename lambda_trait::class_type; + }; +} + +#endif //BLT_META_FUNCTION_H diff --git a/include/blt/meta/passthrough.h b/include/blt/meta/passthrough.h new file mode 100644 index 0000000..3ea369d --- /dev/null +++ b/include/blt/meta/passthrough.h @@ -0,0 +1,31 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see . + */ + +#ifndef BLT_META_PASSTHROUGH_H +#define BLT_META_PASSTHROUGH_H + +namespace blt::meta +{ + template + struct passthrough + { + using type = T; + }; +} + +#endif //BLT_META_PASSTHROUGH_H diff --git a/include/blt/meta/tuple_filters.h b/include/blt/meta/tuple_filters.h new file mode 100644 index 0000000..033d35c --- /dev/null +++ b/include/blt/meta/tuple_filters.h @@ -0,0 +1,80 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see . + */ + +#ifndef BLT_META_FILTER_VOID_H +#define BLT_META_FILTER_VOID_H + +#include +#include + +namespace blt::meta +{ + template + struct filter_void; + + template <> + struct filter_void<> + { + using type = std::tuple<>; + }; + + template + struct filter_void + { + using type = std::conditional_t, typename filter_void::type, decltype(std::tuple_cat( + std::declval>(), std::declval::type>()))>; + }; + + template + struct filter_void> + { + using type = typename filter_void::type; + }; + + template + using filter_void_t = typename filter_void::type; + + template typename Func, typename ArgsTuple, typename... Ts> + struct filter_func; + + template typename Func, typename ArgsTuple> + struct filter_func + { + using type = std::tuple<>; + }; + + template typename Func, typename... Args, typename T, typename... Ts> + struct filter_func, T, Ts...> + { + using type = std::conditional_t::value, typename filter_func, Ts...>::type, decltype( + std::tuple_cat(std::declval>(), + std::declval, Ts...>::type>()))>; + }; + + template typename Func, typename ArgsTuple, typename... Ts> + struct filter_func> + { + using type = typename filter_func::type; + }; + + template typename Func, typename ArgsTuple, typename... Ts> + using filter_func_t = typename filter_func::type; + +} + +#endif //BLT_META_FILTER_VOID_H diff --git a/include/blt/std/variant.h b/include/blt/std/variant.h index dc117f1..da4c108 100644 --- a/include/blt/std/variant.h +++ b/include/blt/std/variant.h @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include namespace blt @@ -33,37 +35,13 @@ namespace blt namespace detail { - template - struct filter_void; - - template <> - struct filter_void<> - { - using type = std::tuple<>; - }; - - template - struct filter_void - { - using type = std::conditional_t, typename filter_void::type, decltype(std::tuple_cat( - std::declval>(), std::declval::type>()))>; - }; - - template - using filter_void_t = typename filter_void::type; - - template - struct passthrough - { - using type = T; - }; - template struct member_func_meta { using can_invoke = std::is_invocable; - using return_type = typename std::conditional_t, passthrough>::type; + using return_type = typename std::conditional_t, meta::passthrough>::type + ; }; template @@ -73,7 +51,7 @@ namespace blt struct member_call_return_type, Types...> { using result_types = std::tuple...>; - using non_void_result_types = typename filter_void::return_type...>::type; + using non_void_result_types = meta::filter_void_t::return_type...>; static constexpr bool all_void = std::tuple_size_v == 0; static constexpr bool some_void = std::tuple_size_v != sizeof...(Types); @@ -83,12 +61,35 @@ namespace blt using return_type = std::conditional_t, first_return>>; }; + template + struct visit_func_meta + { + using result_tuple = std::tuple, std::invoke_result, meta::passthrough>::type...>; + + using non_void_results = meta::filter_void_t; + + using return_type = std::tuple_element_t< + 0, std::conditional_t == 0, std::tuple, non_void_results>>; + }; + template struct visit_return_type; template struct visit_return_type, std::tuple> - {}; + { + using return_tuple = std::tuple::return_type...>; + + using non_void_returns = meta::filter_void_t; + + using first_return = std::tuple_element_t< + 0, std::conditional_t == 0, std::tuple, non_void_returns>>; + + static constexpr bool all_void = std::tuple_size_v == 0; + static constexpr bool some_void = std::tuple_size_v != std::tuple_size_v; + static constexpr bool all_same = meta::filter_func_t, non_void_returns>::value; + }; } /* @@ -214,7 +215,7 @@ namespace blt } template - constexpr auto call_member(const MemberFunc func, Args&&... args) + constexpr auto call_member(const MemberFunc func, Args&&... args) -> decltype(auto) { using meta = detail::member_call_return_type, Types...>; return visit([&](auto&& value) -> typename meta::return_type { @@ -356,12 +357,6 @@ namespace blt } private: - template - static auto cast_member_ptr(ReturnType (Base::*base_func)(Args...)) - { - return reinterpret_cast(base_func); - } - value_type m_variant; }; diff --git a/tests/variant_tests.cpp b/tests/variant_tests.cpp index b0c2e81..6d18ff1 100644 --- a/tests/variant_tests.cpp +++ b/tests/variant_tests.cpp @@ -34,12 +34,12 @@ struct mutate_type : base_type struct type1 final : base_type { - [[nodiscard]] int simple() const override // NOLINT + [[nodiscard]] int simple() const final // NOLINT { return 1; } - [[nodiscard]] std::string to_string() const override // NOLINT + [[nodiscard]] std::string to_string() const final // NOLINT { return "Type1"; } @@ -48,12 +48,12 @@ struct type1 final : base_type struct type2 final : base_type { - [[nodiscard]] int simple() const override // NOLINT + [[nodiscard]] int simple() const final // NOLINT { return 2; } - [[nodiscard]] std::string to_string() const override // NOLINT + [[nodiscard]] std::string to_string() const final // NOLINT { return "Type2"; } @@ -62,12 +62,12 @@ struct type2 final : base_type struct type3 final : base_type { - [[nodiscard]] int simple() const override // NOLINT + [[nodiscard]] int simple() const final // NOLINT { return 3; } - [[nodiscard]] std::string to_string() const override // NOLINT + [[nodiscard]] std::string to_string() const final // NOLINT { return "Type3"; } @@ -79,17 +79,17 @@ struct storing_type1 final : mutate_type { } - [[nodiscard]] int simple() const override // NOLINT + [[nodiscard]] int simple() const final // NOLINT { return internal; } - void mutate(const int i) override + void mutate(const int i) final { internal = i; } - [[nodiscard]] std::string to_string() const override // NOLINT + [[nodiscard]] std::string to_string() const final // NOLINT { return "Storing Type: {" + std::to_string(internal) + "}"; } @@ -103,17 +103,17 @@ struct storing_type2 final : mutate_type { } - [[nodiscard]] int simple() const override // NOLINT + [[nodiscard]] int simple() const final // NOLINT { return static_cast(internal); } - void mutate(const int i) override + void mutate(const int i) final { internal = static_cast(i) * 2.2534f; } - [[nodiscard]] std::string to_string() const override // NOLINT + [[nodiscard]] std::string to_string() const final // NOLINT { return "Storing Type: {" + std::to_string(internal) + "}"; }