tuples!
parent
27c07594a8
commit
84921fffa7
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef BLT_META_FUNCTION_H
|
||||
#define BLT_META_FUNCTION_H
|
||||
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
|
||||
namespace blt::meta
|
||||
{
|
||||
struct std_function_tag
|
||||
{};
|
||||
|
||||
struct function_ptr_tag
|
||||
{};
|
||||
|
||||
struct lambda_tag
|
||||
{};
|
||||
|
||||
struct member_function_ptr_tag
|
||||
{};
|
||||
|
||||
template <typename Func>
|
||||
struct function_like;
|
||||
|
||||
template <typename Return, typename... Args>
|
||||
struct function_like<std::function<Return(Args...)>>
|
||||
{
|
||||
using return_type = Return;
|
||||
using args_tuple = std::tuple<Args...>;
|
||||
using tag = std_function_tag;
|
||||
};
|
||||
|
||||
template <typename Return, typename... Args>
|
||||
struct function_like<Return (*)(Args...)>
|
||||
{
|
||||
using return_type = Return;
|
||||
using args_tuple = std::tuple<Args...>;
|
||||
using tag = function_ptr_tag;
|
||||
};
|
||||
|
||||
template <typename Return, typename... Args>
|
||||
struct function_like<Return (*)(Args...) noexcept>
|
||||
{
|
||||
using return_type = Return;
|
||||
using args_tuple = std::tuple<Args...>;
|
||||
using tag = function_ptr_tag;
|
||||
};
|
||||
|
||||
template <typename Return, typename Class, typename... Args>
|
||||
struct function_like<Return (Class::*)(Args...)>
|
||||
{
|
||||
using return_type = Return;
|
||||
using args_tuple = std::tuple<Args...>;
|
||||
using tag = member_function_ptr_tag;
|
||||
using class_type = Class;
|
||||
};
|
||||
|
||||
template <typename Return, typename Class, typename... Args>
|
||||
struct function_like<Return (Class::*)(Args...) const>
|
||||
{
|
||||
using return_type = Return;
|
||||
using args_tuple = std::tuple<Args...>;
|
||||
using tag = member_function_ptr_tag;
|
||||
using class_type = Class;
|
||||
};
|
||||
|
||||
template <typename Return, typename Class, typename... Args>
|
||||
struct function_like<Return (Class::*)(Args...) noexcept>
|
||||
{
|
||||
using return_type = Return;
|
||||
using args_tuple = std::tuple<Args...>;
|
||||
using tag = member_function_ptr_tag;
|
||||
using class_type = Class;
|
||||
};
|
||||
|
||||
template <typename Return, typename Class, typename... Args>
|
||||
struct function_like<Return (Class::*)(Args...) const noexcept>
|
||||
{
|
||||
using return_type = Return;
|
||||
using args_tuple = std::tuple<Args...>;
|
||||
using tag = member_function_ptr_tag;
|
||||
using class_type = Class;
|
||||
};
|
||||
|
||||
template <typename Func>
|
||||
struct function_like
|
||||
{
|
||||
private:
|
||||
template <typename>
|
||||
struct lambda_traits
|
||||
{};
|
||||
|
||||
template <typename Return, typename Class, typename... Args>
|
||||
struct lambda_traits<Return (Class::*)(Args...) const>
|
||||
{
|
||||
using return_type = Return;
|
||||
using args_tuple = std::tuple<Args...>;
|
||||
using class_type = Class;
|
||||
};
|
||||
|
||||
template <typename Return, typename Class, typename... Args>
|
||||
struct lambda_traits<Return (Class::*)(Args...) noexcept>
|
||||
{
|
||||
using return_type = Return;
|
||||
using args_tuple = std::tuple<Args...>;
|
||||
using class_type = Class;
|
||||
};
|
||||
|
||||
template <typename Return, typename Class, typename... Args>
|
||||
struct lambda_traits<Return (Class::*)(Args...) const noexcept>
|
||||
{
|
||||
using return_type = Return;
|
||||
using args_tuple = std::tuple<Args...>;
|
||||
using class_type = Class;
|
||||
};
|
||||
|
||||
template <typename Return, typename Class, typename... Args>
|
||||
struct lambda_traits<Return (Class::*)(Args...)>
|
||||
{
|
||||
using return_type = Return;
|
||||
using args_tuple = std::tuple<Args...>;
|
||||
using class_type = Class;
|
||||
};
|
||||
|
||||
using lambda_trait = lambda_traits<decltype(&Func::operator())>;
|
||||
|
||||
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
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef BLT_META_PASSTHROUGH_H
|
||||
#define BLT_META_PASSTHROUGH_H
|
||||
|
||||
namespace blt::meta
|
||||
{
|
||||
template <typename T>
|
||||
struct passthrough
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //BLT_META_PASSTHROUGH_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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef BLT_META_FILTER_VOID_H
|
||||
#define BLT_META_FILTER_VOID_H
|
||||
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
namespace blt::meta
|
||||
{
|
||||
template <typename... Ts>
|
||||
struct filter_void;
|
||||
|
||||
template <>
|
||||
struct filter_void<>
|
||||
{
|
||||
using type = std::tuple<>;
|
||||
};
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
struct filter_void<T, Ts...>
|
||||
{
|
||||
using type = std::conditional_t<std::is_void_v<T>, typename filter_void<Ts...>::type, decltype(std::tuple_cat(
|
||||
std::declval<std::tuple<T>>(), std::declval<typename filter_void<Ts...>::type>()))>;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
struct filter_void<std::tuple<Ts...>>
|
||||
{
|
||||
using type = typename filter_void<Ts...>::type;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
using filter_void_t = typename filter_void<Ts...>::type;
|
||||
|
||||
template <template<typename...> typename Func, typename ArgsTuple, typename... Ts>
|
||||
struct filter_func;
|
||||
|
||||
template <template<typename...> typename Func, typename ArgsTuple>
|
||||
struct filter_func<Func, ArgsTuple>
|
||||
{
|
||||
using type = std::tuple<>;
|
||||
};
|
||||
|
||||
template <template<typename...> typename Func, typename... Args, typename T, typename... Ts>
|
||||
struct filter_func<Func, std::tuple<Args...>, T, Ts...>
|
||||
{
|
||||
using type = std::conditional_t<Func<T, Args...>::value, typename filter_func<Func, std::tuple<Args...>, Ts...>::type, decltype(
|
||||
std::tuple_cat(std::declval<std::tuple<T>>(),
|
||||
std::declval<typename filter_func<Func, std::tuple<Args...>, Ts...>::type>()))>;
|
||||
};
|
||||
|
||||
template <template<typename...> typename Func, typename ArgsTuple, typename... Ts>
|
||||
struct filter_func<Func, ArgsTuple, std::tuple<Ts...>>
|
||||
{
|
||||
using type = typename filter_func<Func, ArgsTuple, Ts...>::type;
|
||||
};
|
||||
|
||||
template <template<typename...> typename Func, typename ArgsTuple, typename... Ts>
|
||||
using filter_func_t = typename filter_func<Func, ArgsTuple, Ts...>::type;
|
||||
|
||||
}
|
||||
|
||||
#endif //BLT_META_FILTER_VOID_H
|
|
@ -24,6 +24,8 @@
|
|||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
#include <blt/meta/passthrough.h>
|
||||
#include <blt/meta/tuple_filters.h>
|
||||
#include <blt/std/types.h>
|
||||
|
||||
namespace blt
|
||||
|
@ -33,37 +35,13 @@ namespace blt
|
|||
|
||||
namespace detail
|
||||
{
|
||||
template <typename... Ts>
|
||||
struct filter_void;
|
||||
|
||||
template <>
|
||||
struct filter_void<>
|
||||
{
|
||||
using type = std::tuple<>;
|
||||
};
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
struct filter_void<T, Ts...>
|
||||
{
|
||||
using type = std::conditional_t<std::is_void_v<T>, typename filter_void<Ts...>::type, decltype(std::tuple_cat(
|
||||
std::declval<std::tuple<T>>(), std::declval<typename filter_void<Ts...>::type>()))>;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
using filter_void_t = typename filter_void<Ts...>::type;
|
||||
|
||||
template<typename T>
|
||||
struct passthrough
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename Type, typename Func, typename... Args>
|
||||
struct member_func_meta
|
||||
{
|
||||
using can_invoke = std::is_invocable<Func, Type, Args...>;
|
||||
|
||||
using return_type = typename std::conditional_t<can_invoke::value, std::invoke_result<Func, Type, Args...>, passthrough<void>>::type;
|
||||
using return_type = typename std::conditional_t<can_invoke::value, std::invoke_result<Func, Type, Args...>, meta::passthrough<void>>::type
|
||||
;
|
||||
};
|
||||
|
||||
template <typename Func, typename ArgsTuple, typename... Types>
|
||||
|
@ -73,7 +51,7 @@ namespace blt
|
|||
struct member_call_return_type<Func, std::tuple<Args...>, Types...>
|
||||
{
|
||||
using result_types = std::tuple<member_func_meta<Types, Func, Args...>...>;
|
||||
using non_void_result_types = typename filter_void<typename member_func_meta<Types, Func, Args...>::return_type...>::type;
|
||||
using non_void_result_types = meta::filter_void_t<typename member_func_meta<Types, Func, Args...>::return_type...>;
|
||||
|
||||
static constexpr bool all_void = std::tuple_size_v<non_void_result_types> == 0;
|
||||
static constexpr bool some_void = std::tuple_size_v<non_void_result_types> != sizeof...(Types);
|
||||
|
@ -83,12 +61,35 @@ namespace blt
|
|||
using return_type = std::conditional_t<all_void, void, std::conditional_t<some_void, std::optional<first_return>, first_return>>;
|
||||
};
|
||||
|
||||
template <typename Func, typename... Types>
|
||||
struct visit_func_meta
|
||||
{
|
||||
using result_tuple = std::tuple<typename std::conditional_t<
|
||||
std::is_invocable_v<Func, Types>, std::invoke_result<Func, Types>, meta::passthrough<void>>::type...>;
|
||||
|
||||
using non_void_results = meta::filter_void_t<result_tuple>;
|
||||
|
||||
using return_type = std::tuple_element_t<
|
||||
0, std::conditional_t<std::tuple_size_v<non_void_results> == 0, std::tuple<void>, non_void_results>>;
|
||||
};
|
||||
|
||||
template <typename FuncTuple, typename TypesTuple>
|
||||
struct visit_return_type;
|
||||
|
||||
template <typename... Funcs, typename... Types>
|
||||
struct visit_return_type<std::tuple<Funcs...>, std::tuple<Types...>>
|
||||
{};
|
||||
{
|
||||
using return_tuple = std::tuple<typename visit_func_meta<Funcs, Types...>::return_type...>;
|
||||
|
||||
using non_void_returns = meta::filter_void_t<return_tuple>;
|
||||
|
||||
using first_return = std::tuple_element_t<
|
||||
0, std::conditional_t<std::tuple_size_v<non_void_returns> == 0, std::tuple<void>, non_void_returns>>;
|
||||
|
||||
static constexpr bool all_void = std::tuple_size_v<non_void_returns> == 0;
|
||||
static constexpr bool some_void = std::tuple_size_v<non_void_returns> != std::tuple_size_v<return_tuple>;
|
||||
static constexpr bool all_same = meta::filter_func_t<std::is_same, std::tuple<first_return>, non_void_returns>::value;
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -214,7 +215,7 @@ namespace blt
|
|||
}
|
||||
|
||||
template <typename MemberFunc, typename... Args>
|
||||
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<MemberFunc, std::tuple<Args...>, Types...>;
|
||||
return visit([&](auto&& value) -> typename meta::return_type {
|
||||
|
@ -356,12 +357,6 @@ namespace blt
|
|||
}
|
||||
|
||||
private:
|
||||
template <typename Derived, typename Base, typename ReturnType, typename... Args>
|
||||
static auto cast_member_ptr(ReturnType (Base::*base_func)(Args...))
|
||||
{
|
||||
return reinterpret_cast<ReturnType (Derived::*)(Args...)>(base_func);
|
||||
}
|
||||
|
||||
value_type m_variant;
|
||||
};
|
||||
|
||||
|
|
|
@ -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<int>(internal);
|
||||
}
|
||||
|
||||
void mutate(const int i) override
|
||||
void mutate(const int i) final
|
||||
{
|
||||
internal = static_cast<float>(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) + "}";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue