KDDockWidgets API Documentation 2.0
Loading...
Searching...
No Matches
utils.h
Go to the documentation of this file.
1/*
2 This file is part of KDBindings.
3
4 SPDX-FileCopyrightText: 2021-2023 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
5 Author: Leon Matthes <leon.matthes@kdab.com>
6
7 SPDX-License-Identifier: MIT
8
9 Contact KDAB at <info@kdab.com> for commercial licensing options.
10*/
11#pragma once
12
13#include <functional>
14#include <type_traits>
15#include <utility>
16
17namespace KDBindings {
18
24namespace Private {
25
26// ------------------------ get_arity --------------------------
27// get_arity is a template function that returns the number of arguments
28// of (almost) any callable object.
29// The easiest way is to simply call get_arity<T>() for callable type T.
30// It needs to be constexpr in order so it can be used in template arguments.
31
32// To overload get_arity, it needs a marker type, as C++ doesn't allow partial
33// function specialization.
34template<typename T>
35struct TypeMarker {
36 constexpr TypeMarker() = default;
37};
38
39// base implementation of get_arity refers to specialized implementations for each
40// type of callable object by using the overload for its specialized TypeMarker.
41template<typename T>
42constexpr size_t get_arity()
43{
44 return get_arity(TypeMarker<std::decay_t<T>>{});
45}
46
47// Syntactic sugar version of get_arity, allows to pass any callable object
48// to get_arity, instead of having to pass its decltype as a template argument.
49template<typename T>
50constexpr size_t get_arity(const T &)
51{
52 return get_arity<T>();
53}
54
55// The arity of a function pointer is simply its number of arguments.
56template<typename Return, typename... Arguments>
57constexpr size_t get_arity(TypeMarker<Return (*)(Arguments...)>)
58{
59 return sizeof...(Arguments);
60}
61
62template<typename Return, typename... Arguments>
63constexpr size_t get_arity(TypeMarker<Return (*)(Arguments...) noexcept>)
64{
65 return sizeof...(Arguments);
66}
67
68// The arity of a generic callable object is the arity of its operator() - 1, as the this
69// pointer is already known for such an object.
70template<typename T>
71constexpr size_t get_arity(TypeMarker<T>)
72{
73 return get_arity(TypeMarker<decltype(&T::operator())>{}) - 1;
74}
75
76// Macro to help define most combinations of possible member function qualifiers.
77// Add + 1 to sizeof...(Arguments) here as the "this" pointer is an implicit argument to any member function.
78#define KDBINDINGS_DEFINE_MEMBER_GET_ARITY(MODIFIERS) \
79 template<typename Return, typename Class, typename... Arguments> \
80 constexpr size_t get_arity(::KDBindings::Private::TypeMarker<Return (Class::*)(Arguments...) MODIFIERS>) \
81 { \
82 return sizeof...(Arguments) + 1; \
83 }
84
85// Define the get_arity version without modifiers without using the macro.
86// MSVC otherwise complains about a call to the macro with too few arguments
87template<typename Return, typename Class, typename... Arguments>
89{
90 return sizeof...(Arguments) + 1;
91}
92
98
105
112
119
120// -------------------- placeholder and bind_first ---------------------
121// Inspired by https://gist.github.com/engelmarkus/fc1678adbed1b630584c90219f77eb48
122// A placeholder provides a way to construct something equivalent to a std::placeholders::_N
123// with N as a template argument.
124//
125// Note: As placeholders start at 1, therefore placeholder<0> is NOT a valid placeholder.
126template<int>
129
130template<typename Func, typename... Args, std::size_t... Is>
131auto bind_first_helper(std::index_sequence<Is...>, Func &&fun, Args... args)
132{
133 return std::bind(std::forward<Func>(fun), std::forward<Args>(args)..., placeholder<Is + 1>{}...);
134}
135
136// bind_first binds the first arguments to the callable object (i.e. function) to the values provided by args.
137// The return value is a new function taking get_arity<Func> - sizeof...(Args) many arguments, with the first
138// sizeof...(Args) arguments bound to the values of args.
139// This is different to a call with std::bind(fun, args...), as the callable object created by std::bind would
140// in this case now take zero arguments, whilst bind_first still expects the remaining arguments to be provided
141//
142// For now, providing instances of std::placeholders in Args is not allowed, as the implications of this are
143// unclear if sizeof...(Args) != get_arity<Func>. The enable_if_t makes sure none of the Args value is a placeholder.
144//
145// In the future, we could provide another overload of this function that allows placeholders, as long as all arguments
146// are bound.
147template<
148 typename Func,
149 typename... Args,
150 /*Disallow any placeholder arguments, they would mess with the number and ordering of required and bound arguments, and are, for now, unsupported*/
151 typename = std::enable_if_t<std::conjunction_v<std::negation<std::is_placeholder<Args>>...>>>
153{
154 return bind_first_helper(std::make_index_sequence<get_arity<Func>() - sizeof...(Args)>{}, std::forward<Func>(fun), std::forward<Args>(args)...);
155}
156
157} // namespace Private
158
159} // namespace KDBindings
160
161namespace std {
162
163// This allows a placeholder to be used as a replacement of a std::placeholders.
164template<int N>
165struct is_placeholder<KDBindings::Private::placeholder<N>>
166 : integral_constant<int, N> {
167};
168
169} // namespace std
auto bind_first(Func &&fun, Args &&...args)
Definition utils.h:152
typename operator_node_result< Operator, Ts... >::type operator_node_result_t
Definition make_node.h:57
constexpr size_t get_arity()
Definition utils.h:42
auto bind_first_helper(std::index_sequence< Is... >, Func &&fun, Args... args)
Definition utils.h:131
The main namespace of the KDBindings library.
Definition binding.h:21
Definition utils.h:161
constexpr TypeMarker()=default
#define KDBINDINGS_DEFINE_MEMBER_GET_ARITY(MODIFIERS)
Definition utils.h:78

© Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
KDDockWidgets
Advanced Dock Widget Framework for Qt
https://www.kdab.com/development-resources/qt-tools/kddockwidgets/
Generated by doxygen 1.9.8