based

Opinionated utility library
git clone git://git.dimitrijedobrota.com/based.git
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING

commit de074c7f42b48b82fa4c10b1ae5542c608741f4c
parent e5785277f51a5e5118eb00fd5b09b6785cfc0871
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Thu, 8 May 2025 16:46:50 +0200

Redundancy cleanup

Diffstat:
M include/based/concepts/procedure/procedure.hpp | + -
D include/based/count.hpp | --------------------------------------------------
M include/based/enum/enum.hpp | + -
A include/based/macro/macros.hpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D include/based/macros.hpp | ---------------------------------------------------------------------------------
D include/based/string.hpp | ------------------------
A include/based/string/literal.hpp | ++++++++++++++++++++++++
D include/based/trait/invoke/result.hpp | ---------------------------------------------------------------------------------
A include/based/trait/invoke_result.hpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D include/based/utility.hpp |
M test/source/string_literal_test.cpp | ++ --
M test/source/trait/invoke_result_test.cpp | ++++++++++++ -----

12 files changed, 210 insertions(+), 260 deletions(-)


diff --git a/ include/based/concepts/procedure/procedure.hpp b/ include/based/concepts/procedure/procedure.hpp

@@ -5,7 +5,7 @@

#include "based/concepts/is/regular.hpp"
#include "based/concepts/procedure/domain.hpp"
#include "based/trait/integral_constant.hpp"
#include "based/trait/invoke/result.hpp"
#include "based/trait/invoke_result.hpp"

namespace based
{

diff --git a/ include/based/count.hpp b/ include/based/count.hpp

@@ -1,50 +0,0 @@

#pragma once

#include "based/concepts/iterator.hpp"
#include "based/trait/iterator.hpp"

namespace based
{

template<ReadableIterator I, Iterator J>
J count(I first, I last, const iter_value_t<I>& val, J cnt)
{
// Precondition: readable_bounded_range(first, last);
while (first != last) {
if (*first == val) {
cnt++;
}
first++;
}
return cnt;
}

template<ReadableIterator I>
iter_dist_t<I> count(I first, I last, const iter_value_t<I>& val)
{
// Precondition: readable_bounded_range(first, last);
return count(first, last, val, iter_dist_t<I> {0});
}

template<ReadableIterator I, Iterator J>
auto count_n(I first, iter_dist_t<I> size, const iter_value_t<I>& val, J cnt)
{
// Precondition: readable_weak_range(first, size);
while (size != 0) {
if (*first == val) {
cnt++;
}
size--;
first++;
}
return std::make_pair(first, cnt);
}

template<ReadableIterator I>
auto count_n(I first, iter_dist_t<I> size, const iter_value_t<I>& val)
{
// Precondition: readable_weak_range(first, size);
return count_n(first, size, val, iter_dist_t<I> {0});
}

} // namespace based

diff --git a/ include/based/enum/enum.hpp b/ include/based/enum/enum.hpp

@@ -3,7 +3,7 @@

#include <array>
#include <cassert>

#include "based/macros.hpp"
#include "based/macro/macros.hpp"
#include "based/utility/forward.hpp"

// NOLINTBEGIN(*macro-usage*)

diff --git a/ include/based/macro/macros.hpp b/ include/based/macro/macros.hpp

@@ -0,0 +1,87 @@

#pragma once

// NOLINTBEGIN(*macro-usage*)

#define BASED_NUMARGS(...) (std::array {__VA_ARGS__}.size())

// clang-format off
#define BASED_GET_MACRO( \
_0, _1, _2, _3, _4, _5, _6, _7, \
_8, _9, _10, _11, _12, _13, _14, _15, \
NAME, ... \
) NAME
// clang-format on

// clang-format off
#define BASED_FE_0(WHAT)
#define BASED_FE_1(WHAT, X) WHAT(X, 0)
#define BASED_FE_2(WHAT, X, ...) WHAT(X, 1) BASED_FE_1(WHAT, __VA_ARGS__)
#define BASED_FE_3(WHAT, X, ...) WHAT(X, 2) BASED_FE_2(WHAT, __VA_ARGS__)
#define BASED_FE_4(WHAT, X, ...) WHAT(X, 3) BASED_FE_3(WHAT, __VA_ARGS__)
#define BASED_FE_5(WHAT, X, ...) WHAT(X, 4) BASED_FE_4(WHAT, __VA_ARGS__)
#define BASED_FE_6(WHAT, X, ...) WHAT(X, 5) BASED_FE_5(WHAT, __VA_ARGS__)
#define BASED_FE_7(WHAT, X, ...) WHAT(X, 6) BASED_FE_6(WHAT, __VA_ARGS__)
#define BASED_FE_8(WHAT, X, ...) WHAT(X, 7) BASED_FE_7(WHAT, __VA_ARGS__)
#define BASED_FE_9(WHAT, X, ...) WHAT(X, 8) BASED_FE_8(WHAT, __VA_ARGS__)
#define BASED_FE_10(WHAT, X, ...) WHAT(X, 9) BASED_FE_9(WHAT, __VA_ARGS__)
#define BASED_FE_11(WHAT, X, ...) WHAT(X, 10) BASED_FE_10(WHAT, __VA_ARGS__)
#define BASED_FE_12(WHAT, X, ...) WHAT(X, 11) BASED_FE_11(WHAT, __VA_ARGS__)
#define BASED_FE_13(WHAT, X, ...) WHAT(X, 12) BASED_FE_12(WHAT, __VA_ARGS__)
#define BASED_FE_14(WHAT, X, ...) WHAT(X, 13) BASED_FE_13(WHAT, __VA_ARGS__)
#define BASED_FE_15(WHAT, X, ...) WHAT(X, 14) BASED_FE_14(WHAT, __VA_ARGS__)
// clang-format on

#define BASED_FOREACH(action, ...) \
BASED_GET_MACRO(_0, __VA_ARGS__, BASED_FE_15, BASED_FE_14, BASED_FE_13, BASED_FE_12, BASED_FE_11, BASED_FE_10, BASED_FE_9, BASED_FE_8, BASED_FE_7, BASED_FE_6, BASED_FE_5, BASED_FE_4, BASED_FE_3, BASED_FE_2, BASED_FE_1, BASED_FE_0)( \
action, __VA_ARGS__ \
)

// clang-format off
#define BASED_FE_0_1(First, WHAT)
#define BASED_FE_1_1(First, WHAT, X) WHAT(First, X, 0)
#define BASED_FE_2_1(First, WHAT, X, ...) WHAT(First, X, 1) BASED_FE_1_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_3_1(First, WHAT, X, ...) WHAT(First, X, 2) BASED_FE_2_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_4_1(First, WHAT, X, ...) WHAT(First, X, 3) BASED_FE_3_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_5_1(First, WHAT, X, ...) WHAT(First, X, 4) BASED_FE_4_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_6_1(First, WHAT, X, ...) WHAT(First, X, 5) BASED_FE_5_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_7_1(First, WHAT, X, ...) WHAT(First, X, 6) BASED_FE_6_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_8_1(First, WHAT, X, ...) WHAT(First, X, 7) BASED_FE_7_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_9_1(First, WHAT, X, ...) WHAT(First, X, 8) BASED_FE_8_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_10_1(First, WHAT, X, ...) WHAT(First, X, 9) BASED_FE_9_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_11_1(First, WHAT, X, ...) WHAT(First, X, 10) BASED_FE_10_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_12_1(First, WHAT, X, ...) WHAT(First, X, 11) BASED_FE_11_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_13_1(First, WHAT, X, ...) WHAT(First, X, 12) BASED_FE_12_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_14_1(First, WHAT, X, ...) WHAT(First, X, 13) BASED_FE_13_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_15_1(First, WHAT, X, ...) WHAT(First, X, 14) BASED_FE_14_1(First, WHAT, __VA_ARGS__)
// clang-format on

#define BASED_FOREACH_1(First, action, ...) \
BASED_GET_MACRO(_0, __VA_ARGS__, BASED_FE_15_1, BASED_FE_14_1, BASED_FE_13_1, BASED_FE_12_1, BASED_FE_11_1, BASED_FE_10_1, BASED_FE_9_1, BASED_FE_8_1, BASED_FE_7_1, BASED_FE_6_1, BASED_FE_5_1, BASED_FE_4_1, BASED_FE_3_1, BASED_FE_2_1, BASED_FE_1_1, BASED_FE_0_1)( \
First, action, __VA_ARGS__ \
)

// clang-format off
#define BASED_FE_0_2(First, Second, WHAT)
#define BASED_FE_1_2(First, Second, WHAT, X) WHAT(First, Second, X, 0)
#define BASED_FE_2_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 1) BASED_FE_1_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_3_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 2) BASED_FE_2_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_4_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 3) BASED_FE_3_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_5_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 4) BASED_FE_4_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_6_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 5) BASED_FE_5_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_7_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 6) BASED_FE_6_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_8_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 7) BASED_FE_7_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_9_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 8) BASED_FE_8_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_10_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 9) BASED_FE_9_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_11_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 10) BASED_FE_10_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_12_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 11) BASED_FE_11_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_13_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 12) BASED_FE_12_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_14_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 13) BASED_FE_13_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_15_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 14) BASED_FE_14_2(First, Second, WHAT, __VA_ARGS__)
// clang-format on

#define BASED_FOREACH_2(First, Second, action, ...) \
BASED_GET_MACRO(_0, __VA_ARGS__, BASED_FE_15_2, BASED_FE_14_2, BASED_FE_13_2, BASED_FE_12_2, BASED_FE_11_2, BASED_FE_10_2, BASED_FE_9_2, BASED_FE_8_2, BASED_FE_7_2, BASED_FE_6_2, BASED_FE_5_2, BASED_FE_4_2, BASED_FE_3_2, BASED_FE_2_2, BASED_FE_1_2, BASED_FE_0_2)( \
First, Second, action, __VA_ARGS__ \
)

// NOLINTEND(*macro-usage*)

diff --git a/ include/based/macros.hpp b/ include/based/macros.hpp

@@ -1,87 +0,0 @@

#pragma once

// NOLINTBEGIN(*macro-usage*)

#define BASED_NUMARGS(...) (std::array {__VA_ARGS__}.size())

// clang-format off
#define BASED_GET_MACRO( \
_0, _1, _2, _3, _4, _5, _6, _7, \
_8, _9, _10, _11, _12, _13, _14, _15, \
NAME, ... \
) NAME
// clang-format on

// clang-format off
#define BASED_FE_0(WHAT)
#define BASED_FE_1(WHAT, X) WHAT(X, 0)
#define BASED_FE_2(WHAT, X, ...) WHAT(X, 1) BASED_FE_1(WHAT, __VA_ARGS__)
#define BASED_FE_3(WHAT, X, ...) WHAT(X, 2) BASED_FE_2(WHAT, __VA_ARGS__)
#define BASED_FE_4(WHAT, X, ...) WHAT(X, 3) BASED_FE_3(WHAT, __VA_ARGS__)
#define BASED_FE_5(WHAT, X, ...) WHAT(X, 4) BASED_FE_4(WHAT, __VA_ARGS__)
#define BASED_FE_6(WHAT, X, ...) WHAT(X, 5) BASED_FE_5(WHAT, __VA_ARGS__)
#define BASED_FE_7(WHAT, X, ...) WHAT(X, 6) BASED_FE_6(WHAT, __VA_ARGS__)
#define BASED_FE_8(WHAT, X, ...) WHAT(X, 7) BASED_FE_7(WHAT, __VA_ARGS__)
#define BASED_FE_9(WHAT, X, ...) WHAT(X, 8) BASED_FE_8(WHAT, __VA_ARGS__)
#define BASED_FE_10(WHAT, X, ...) WHAT(X, 9) BASED_FE_9(WHAT, __VA_ARGS__)
#define BASED_FE_11(WHAT, X, ...) WHAT(X, 10) BASED_FE_10(WHAT, __VA_ARGS__)
#define BASED_FE_12(WHAT, X, ...) WHAT(X, 11) BASED_FE_11(WHAT, __VA_ARGS__)
#define BASED_FE_13(WHAT, X, ...) WHAT(X, 12) BASED_FE_12(WHAT, __VA_ARGS__)
#define BASED_FE_14(WHAT, X, ...) WHAT(X, 13) BASED_FE_13(WHAT, __VA_ARGS__)
#define BASED_FE_15(WHAT, X, ...) WHAT(X, 14) BASED_FE_14(WHAT, __VA_ARGS__)
// clang-format on

#define BASED_FOREACH(action, ...) \
BASED_GET_MACRO(_0, __VA_ARGS__, BASED_FE_15, BASED_FE_14, BASED_FE_13, BASED_FE_12, BASED_FE_11, BASED_FE_10, BASED_FE_9, BASED_FE_8, BASED_FE_7, BASED_FE_6, BASED_FE_5, BASED_FE_4, BASED_FE_3, BASED_FE_2, BASED_FE_1, BASED_FE_0)( \
action, __VA_ARGS__ \
)

// clang-format off
#define BASED_FE_0_1(First, WHAT)
#define BASED_FE_1_1(First, WHAT, X) WHAT(First, X, 0)
#define BASED_FE_2_1(First, WHAT, X, ...) WHAT(First, X, 1) BASED_FE_1_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_3_1(First, WHAT, X, ...) WHAT(First, X, 2) BASED_FE_2_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_4_1(First, WHAT, X, ...) WHAT(First, X, 3) BASED_FE_3_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_5_1(First, WHAT, X, ...) WHAT(First, X, 4) BASED_FE_4_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_6_1(First, WHAT, X, ...) WHAT(First, X, 5) BASED_FE_5_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_7_1(First, WHAT, X, ...) WHAT(First, X, 6) BASED_FE_6_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_8_1(First, WHAT, X, ...) WHAT(First, X, 7) BASED_FE_7_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_9_1(First, WHAT, X, ...) WHAT(First, X, 8) BASED_FE_8_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_10_1(First, WHAT, X, ...) WHAT(First, X, 9) BASED_FE_9_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_11_1(First, WHAT, X, ...) WHAT(First, X, 10) BASED_FE_10_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_12_1(First, WHAT, X, ...) WHAT(First, X, 11) BASED_FE_11_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_13_1(First, WHAT, X, ...) WHAT(First, X, 12) BASED_FE_12_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_14_1(First, WHAT, X, ...) WHAT(First, X, 13) BASED_FE_13_1(First, WHAT, __VA_ARGS__)
#define BASED_FE_15_1(First, WHAT, X, ...) WHAT(First, X, 14) BASED_FE_14_1(First, WHAT, __VA_ARGS__)
// clang-format on

#define BASED_FOREACH_1(First, action, ...) \
BASED_GET_MACRO(_0, __VA_ARGS__, BASED_FE_15_1, BASED_FE_14_1, BASED_FE_13_1, BASED_FE_12_1, BASED_FE_11_1, BASED_FE_10_1, BASED_FE_9_1, BASED_FE_8_1, BASED_FE_7_1, BASED_FE_6_1, BASED_FE_5_1, BASED_FE_4_1, BASED_FE_3_1, BASED_FE_2_1, BASED_FE_1_1, BASED_FE_0_1)( \
First, action, __VA_ARGS__ \
)

// clang-format off
#define BASED_FE_0_2(First, Second, WHAT)
#define BASED_FE_1_2(First, Second, WHAT, X) WHAT(First, Second, X, 0)
#define BASED_FE_2_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 1) BASED_FE_1_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_3_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 2) BASED_FE_2_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_4_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 3) BASED_FE_3_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_5_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 4) BASED_FE_4_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_6_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 5) BASED_FE_5_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_7_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 6) BASED_FE_6_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_8_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 7) BASED_FE_7_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_9_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 8) BASED_FE_8_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_10_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 9) BASED_FE_9_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_11_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 10) BASED_FE_10_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_12_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 11) BASED_FE_11_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_13_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 12) BASED_FE_12_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_14_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 13) BASED_FE_13_2(First, Second, WHAT, __VA_ARGS__)
#define BASED_FE_15_2(First, Second, WHAT, X, ...) WHAT(First, Second, X, 14) BASED_FE_14_2(First, Second, WHAT, __VA_ARGS__)
// clang-format on

#define BASED_FOREACH_2(First, Second, action, ...) \
BASED_GET_MACRO(_0, __VA_ARGS__, BASED_FE_15_2, BASED_FE_14_2, BASED_FE_13_2, BASED_FE_12_2, BASED_FE_11_2, BASED_FE_10_2, BASED_FE_9_2, BASED_FE_8_2, BASED_FE_7_2, BASED_FE_6_2, BASED_FE_5_2, BASED_FE_4_2, BASED_FE_3_2, BASED_FE_2_2, BASED_FE_1_2, BASED_FE_0_2)( \
First, Second, action, __VA_ARGS__ \
)

// NOLINTEND(*macro-usage*)

diff --git a/ include/based/string.hpp b/ include/based/string.hpp

@@ -1,24 +0,0 @@

#pragma once

#include <array>
#include <cstddef>

namespace based
{

template<size_t n>
struct string_literal
{
// NOLINTNEXTLINE(*explicit*, *array*)
constexpr string_literal(const char (&str)[n])
: m_value(std::to_array(str))
{
}

[[nodiscard]] constexpr size_t size() const { return n; }
[[nodiscard]] constexpr const char* data() const { return m_value.data(); }

std::array<char, n> m_value;
};

} // namespace based

diff --git a/ include/based/string/literal.hpp b/ include/based/string/literal.hpp

@@ -0,0 +1,24 @@

#pragma once

#include <array>
#include <cstddef>

namespace based
{

template<size_t n>
struct string_literal
{
// NOLINTNEXTLINE(*explicit*, *array*)
constexpr string_literal(const char (&str)[n])
: m_value(std::to_array(str))
{
}

[[nodiscard]] constexpr size_t size() const { return n; }
[[nodiscard]] constexpr const char* data() const { return m_value.data(); }

std::array<char, n> m_value;
};

} // namespace based

diff --git a/ include/based/trait/invoke/result.hpp b/ include/based/trait/invoke/result.hpp

@@ -1,90 +0,0 @@

#pragma once

#include "based/trait/decay.hpp"
#include "based/trait/is/base_of.hpp"
#include "based/trait/is/reference_wrapper.hpp"
#include "based/utility/forward.hpp"

namespace based
{

namespace detail
{

template<class T>
struct invoke_impl
{
template<class F, class... Args>
static auto call(F&& func, Args&&... args)
-> decltype(based::forward<F>(func)(based::forward<Args>(args)...));
};

template<class B, class MT>
struct invoke_impl<MT B::*>
{
template<class T>
requires(is_base_of_v<B, decay_t<T>>)
static auto get(T&& obj) -> T&&;

template<class T>
requires(is_reference_wrapper_v<decay_t<T>>)
static auto get(T&& obj) -> decltype(obj.get());

template<class T>
requires(!is_base_of_v<B, decay_t<T>> && !is_reference_wrapper_v<decay<T>>)
static auto get(T&& obj) -> decltype(*based::forward<T>(obj));

template<class T, class... Args, class MT1>
requires(is_function_v<MT1>)
static auto call(MT1 B::* pmf, T&& obj, Args&&... args)
-> decltype((invoke_impl::get(based::forward<T>(obj)).*pmf)(based::forward<Args>(args
)...));

template<class T>
static auto call(MT B::* pmd, T&& obj)
-> decltype(invoke_impl::get(based::forward<T>(obj)).*pmd);
};

template<class F, class... Args>
auto INVOKE(F&& func, Args&&... args) -> decltype(invoke_impl<decay_t<F>>::call(
based::forward<F>(func), based::forward<Args>(args)...
));

} // namespace detail

namespace detail
{

template<typename AlwaysVoid, typename, typename...>
struct invoke_result
{
};

template<typename F, typename... Args>
struct invoke_result<
decltype(void(detail::INVOKE(declval<F>(), declval<Args>()...))),
F,
Args...>
{
using type = decltype(detail::INVOKE(declval<F>(), declval<Args>()...));
};

} // namespace detail

/*
template<class F, class... Args>
struct invoke_result : detail::invoke_result<void, F, Args...>
{
};

template<class F, class... Args>
using invoke_result_t = typename invoke_result<F, Args...>::type;
*/

template<class F, class... Args>
using invoke_result = std::invoke_result<F, Args...>;

template<class F, class... Args>
using invoke_result_t = std::invoke_result_t<F, Args...>;

} // namespace based

diff --git a/ include/based/trait/invoke_result.hpp b/ include/based/trait/invoke_result.hpp

@@ -0,0 +1,83 @@

#pragma once

#include "based/trait/decay.hpp"
#include "based/trait/is/base_of.hpp"
#include "based/trait/is/reference_wrapper.hpp"
#include "based/utility/forward.hpp"

namespace based
{

namespace detail
{

template<class T>
struct invoke_impl
{
template<class F, class... Args>
static auto call(F&& func, Args&&... args)
-> decltype(based::forward<F>(func)(based::forward<Args>(args)...));
};

template<class B, class MT>
struct invoke_impl<MT B::*>
{
template<class T>
requires(is_base_of_v<B, decay_t<T>>)
static auto get(T&& obj) -> T&&;

template<class T>
requires(is_reference_wrapper_v<decay_t<T>>)
static auto get(T&& obj) -> decltype(obj.get());

template<class T>
requires(!is_base_of_v<B, decay_t<T>> && !is_reference_wrapper_v<decay<T>>)
static auto get(T&& obj) -> decltype(*based::forward<T>(obj));

template<class T, class... Args, class MT1>
requires(is_function_v<MT1>)
static auto call(MT1 B::* pmf, T&& obj, Args&&... args)
-> decltype((invoke_impl::get(based::forward<T>(obj)).*pmf)(
based::forward<Args>(args)...
));

template<class T>
static auto call(MT B::* pmd, T&& obj)
-> decltype(invoke_impl::get(based::forward<T>(obj)).*pmd);
};

template<class F, class... Args>
auto INVOKE(F&& func, Args&&... args) -> decltype(invoke_impl<decay_t<F>>::call(
based::forward<F>(func), based::forward<Args>(args)...
));

} // namespace detail

namespace detail
{

template<typename AlwaysVoid, typename, typename...>
struct invoke_result
{
};

template<typename F, typename... Args>
struct invoke_result<
decltype(void(detail::INVOKE(declval<F>(), declval<Args>()...))),
F,
Args...>
{
using type = decltype(detail::INVOKE(declval<F>(), declval<Args>()...));
};

} // namespace detail

template<class F, class... Args>
struct invoke_result : detail::invoke_result<void, F, Args...>
{
};

template<class F, class... Args>
using invoke_result_t = typename invoke_result<F, Args...>::type;

} // namespace based

diff --git a/ include/based/utility.hpp b/ include/based/utility.hpp

diff --git a/ test/source/string_literal_test.cpp b/ test/source/string_literal_test.cpp

@@ -1,7 +1,7 @@

#include "based/string.hpp"

#include <catch2/catch_test_macros.hpp>

#include "based/string/literal.hpp"

TEST_CASE("empty", "[string/string_literal]")
{
const based::string_literal sltr = "";

diff --git a/ test/source/trait/invoke_result_test.cpp b/ test/source/trait/invoke_result_test.cpp

@@ -1,24 +1,31 @@

#define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE

#include "based/trait/invoke_result.hpp"

#include <catch2/catch_test_macros.hpp>

#include "based/concepts/is/same.hpp"
#include "based/trait/invoke/result.hpp"

namespace
{

// NOLINTNEXTLINE(*needed*)
int func(double);

} // namespace

template<class Res, class T, class... Args>
concept test = based::SameAs<based::invoke_result_t<T(Args...)>, Res>;
concept test = based::SameAs<based::invoke_result_t<T, Args...>, Res>;

TEST_CASE("invoke_result", "[trait/invoke_result]")
{
// NOLINTBEGIN(*array*)
// clang-format off
/*

STATIC_REQUIRE(test<int, decltype(func), double>);
STATIC_REQUIRE(test<int, decltype(func), int>);
STATIC_REQUIRE(!test<int, decltype(func), char>);
*/
STATIC_REQUIRE(!test<int, decltype(func), decltype(func)>);

// clang-format on
// NOLINTEND(*array*)
}