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) + "}";
}