guanaqo main
Utilities for scientific software
Loading...
Searching...
No Matches
tag-invoke.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file
4/// @ingroup customization
5/// tag_invoke customization point and concepts.
6/// @see https://wg21.link/P1895R0
7/// @see https://wg21.link/P2547R0
8
9#include <guanaqo/compiler.h>
10#include <type_traits>
11#include <utility>
12
13namespace guanaqo {
14
16
17/// Poison pill to hide overloads of foo() that might be found in parent
18/// namespace.
19/// We want to limit to only finding overloads by ADL.
20#if defined(_MSC_VER) || GUANAQO_GCC_OLDER_THAN(12)
21void guanaqo_tag_invoke() /* = delete */;
22#else
23void guanaqo_tag_invoke() = delete;
24#endif
25
27 template <typename Tag, typename... Args>
28 requires requires(Tag tag, Args &&...args) {
29 guanaqo_tag_invoke(std::move(tag), std::forward<Args>(args)...);
30 }
31 constexpr auto operator()(Tag tag, Args &&...args) const
32 noexcept(noexcept(guanaqo_tag_invoke(std::move(tag),
33 std::forward<Args>(args)...)))
34 -> decltype(guanaqo_tag_invoke(std::move(tag),
35 std::forward<Args>(args)...)) {
36 return guanaqo_tag_invoke(std::move(tag), std::forward<Args>(args)...);
37 }
38};
39} // namespace tag_invoke_fn_ns
40
41// Function object needs to be in a separate namespace to avoid conflicts with
42// hidden-friend customizations defined for types in the guanaqo namespace.
43inline namespace tag_invoke_ns {
44/// The tag_invoke customization point object.
45/// @ingroup customization
47}
48
49/// @addtogroup customization
50/// @{
51
52template <typename Tag, typename... Args>
53concept tag_invocable = requires(Tag tag, Args... args) {
54 guanaqo_tag_invoke(std::forward<Tag>(tag), std::forward<Args>(args)...);
55};
56
57template <typename Tag, typename... Args>
59 tag_invocable<Tag, Args...> && requires(Tag tag, Args... args) {
60 {
61 guanaqo_tag_invoke(std::forward<Tag>(tag),
62 std::forward<Args>(args)...)
63 } noexcept;
64 };
65
66template <typename Tag, typename... Args>
67inline constexpr bool is_tag_invocable_v = tag_invocable<Tag, Args...>;
68
69template <typename Tag, typename... Args>
70inline constexpr bool is_nothrow_tag_invocable_v =
71 nothrow_tag_invocable<Tag, Args...>;
72
73template <typename Tag, typename... Args>
75 std::invoke_result<decltype(::guanaqo::guanaqo_tag_invoke), Tag, Args...>;
76
77template <typename Tag, typename... Args>
79 std::invoke_result_t<decltype(::guanaqo::guanaqo_tag_invoke), Tag, Args...>;
80
81template <auto &Tag>
82using tag_t = std::decay_t<decltype(Tag)>;
83
84/// @}
85
86} // namespace guanaqo
Compiler feature detection helpers.
std::decay_t< decltype(Tag)> tag_t
constexpr bool is_nothrow_tag_invocable_v
constexpr tag_invoke_fn_ns::tag_invoke_fn guanaqo_tag_invoke
The tag_invoke customization point object.
std::invoke_result< decltype(::guanaqo::guanaqo_tag_invoke), Tag, Args... > tag_invoke_result
constexpr bool is_tag_invocable_v
std::invoke_result_t< decltype(::guanaqo::guanaqo_tag_invoke), Tag, Args... > tag_invoke_result_t
void guanaqo_tag_invoke()=delete
Poison pill to hide overloads of foo() that might be found in parent namespace.
constexpr auto operator()(Tag tag, Args &&...args) const noexcept(noexcept(guanaqo_tag_invoke(std::move(tag), std::forward< Args >(args)...))) -> decltype(guanaqo_tag_invoke(std::move(tag), std::forward< Args >(args)...))