Lagrange
template.h
1/*
2 * Copyright 2020 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12#pragma once
13#include <lagrange/utils/assert.h>
14#include <lagrange/utils/strings.h>
15#include <lagrange/utils/warning.h>
16
17#include <any>
18#include <functional>
19
20
21namespace lagrange {
22namespace ui {
23
24
25namespace util {
26
27template <typename F>
29
30template <typename F, typename Result, typename... Args>
31struct lambda_helper<Result (F::*)(Args...) const>
32{
33 using fn_type = std::function<Result(Args...)>;
34};
35} // namespace util
36
37namespace util {
38
39template <class T>
40struct AsFunction : public AsFunction<decltype(&T::operator())>
41{
42};
43
44template <class Class, class ReturnType, class Arg>
45struct AsFunction<ReturnType (Class::*)(Arg) const>
46{
47 using arg_type = Arg;
48};
49
50template <class ReturnType, class Arg>
51struct AsFunction<ReturnType (*)(Arg)>
52{
53 using arg_type = Arg;
54};
55
56template <class ReturnType, class Arg>
57struct AsFunction<ReturnType(Arg) const>
58{
59 using arg_type = Arg;
60};
61
62} // namespace util
63
64namespace detail {
65
66
67template <typename T>
69{
70 using type = std::conditional_t<std::is_same<T, const char*>::value, std::string, T>;
71};
72
73template <typename T>
74using convert_implicit_t = typename convert_implicit<T>::type;
75
76
77template <typename... Args>
79{
80 using type = std::tuple<std::remove_cv_t<std::remove_reference_t<convert_implicit_t<Args>>>...>;
81};
82
83template <typename... Args>
84using args_to_tuple_t = typename args_to_tuple<Args...>::type;
85
86
87template <typename T>
88std::unique_ptr<T> realize_default(
89 typename std::enable_if<std::is_default_constructible<T>::value>::type* dummy = 0)
90{
91 LA_IGNORE(dummy);
92 return std::make_unique<T>();
93}
94
95template <typename T>
96std::unique_ptr<T> realize_default(
97 typename std::enable_if<!std::is_default_constructible<T>::value>::type* dummy = 0)
98{
99 LA_IGNORE(dummy);
100
102 false,
104 "Cannot default construct type {}, provide a realization function to ResourceFactory",
105 typeid(T).name()));
106 return nullptr;
107}
108
109
110template <typename T, typename... Dummy>
111std::shared_ptr<T> realize_forward(const std::shared_ptr<T>& ptr)
112{
113 return ptr;
114}
115
116template <typename T, typename... Args>
117std::shared_ptr<T> realize_forward(
118 Args... args,
119 typename std::enable_if<std::is_constructible<T, Args...>::value>::type* dummy = 0)
120{
121 LA_IGNORE(dummy);
122 return std::make_shared<T>(std::forward<Args>(args)...);
123}
124
125template <typename... Args>
126void unused_variadic(Args&&... args)
127{
128 LA_IGNORE(sizeof...(args));
129}
130
131
132// Enabled if:
133// 1. Cannot construct type T from Args
134// 2. Cannot construct shared_ptr<T> from Args (makes sure this doesn't shadow realize_forward(const
135// std::shared_ptr<T>&ptr))
136// 3. Cannot construct unique_tr<T> from Args (makes sure this doesn't shadow
137// realize_forward(std::unique_ptr<T>&&))
138template <typename T, typename... Args>
139std::shared_ptr<T> realize_forward(
140 Args... args,
141 typename std::enable_if<
142 !std::is_constructible<T, Args...>::value &&
143 !std::is_constructible<std::shared_ptr<T>, Args...>::value &&
144 !std::is_constructible<std::unique_ptr<T>, Args...>::value>::type* dummy = 0)
145{
146 LA_IGNORE(dummy);
147 unused_variadic(std::forward<Args>(args)...);
149 false,
151 "Cannot construct type {} from given arguments {}, provide a realization function to "
152 "ResourceFactory",
153 typeid(T).name(),
154 typeid(std::tuple<Args...>).name()));
155
156 return nullptr;
157}
158
159// Simply copies the data
160template <typename T_out, typename T_in>
161T_out copy_or_move_element(
162 T_in& in,
163 typename std::enable_if<!std::is_rvalue_reference<T_out>::value>::type* dummy = 0)
164{
165 LA_IGNORE(dummy);
166 return in;
167}
168
169// Moves out the data
170template <typename T_out, typename T_in>
171std::remove_reference_t<T_out> copy_or_move_element(
172 T_in& in,
173 typename std::enable_if<std::is_rvalue_reference<T_out>::value>::type* dummy = 0)
174{
175 LA_IGNORE(dummy);
176 std::remove_reference_t<T_out> moved = std::move(in);
177 return moved;
178}
179
181template <typename ArgumentTuple, typename... Ts, size_t... Is>
182auto copy_or_move_impl(std::tuple<Ts...>& input, std::index_sequence<Is...>)
183{
184 return std::tuple<Ts...>{
185 copy_or_move_element<std::tuple_element_t<Is, ArgumentTuple>>(std::get<Is>(input))...};
186}
187
189template <typename ArgumentTuple, typename... Ts>
190std::tuple<Ts...> copy_or_move(std::tuple<Ts...>& input)
191{
192 return copy_or_move_impl<ArgumentTuple>(input, std::make_index_sequence<sizeof...(Ts)>{});
193}
194
195template <typename ParamPack, typename ParamPackOriginal, typename F>
196void apply_parameters(
197 const F& fn,
198 std::any& storage,
199 typename std::enable_if<std::is_constructible<ParamPack, const ParamPack&>::value>::type*
200 dummy = 0)
201{
202 LA_IGNORE(dummy);
203 // If original param pack require rvalue reference, move the data, otherwise copy
204 auto& storage_tuple = std::any_cast<ParamPack&>(storage);
205 auto forwarded_tuple = copy_or_move<ParamPackOriginal>(storage_tuple);
206
207 std::apply(fn, std::move(forwarded_tuple));
208}
209
210
211template <typename ParamPack, typename ParamPackOriginal, typename F>
212void apply_parameters(
213 const F& fn,
214 std::any& storage,
215 typename std::enable_if<!std::is_constructible<ParamPack, const ParamPack&>::value>::type*
216 dummy = 0)
217{
218 // Do nothing
219 LA_IGNORE(fn);
220 LA_IGNORE(storage);
221 LA_IGNORE(dummy);
222 // Execution should not reach here as non-copyable arguments can't be saved to std::any
223}
224
225
226} // namespace detail
227
228} // namespace ui
229} // namespace lagrange
#define la_runtime_assert(...)
Runtime assertion check.
Definition: assert.h:169
std::string string_format(fmt::format_string< Args... > format, Args &&... args)
Format args according to the format string fmt, and return the result as a string.
Definition: strings.h:103
#define LA_IGNORE(x)
Ignore x to avoid an unused variable warning.
Definition: warning.h:136
Lagrange UI Viewer and mini 3D engine.
Definition: AcceleratedPicking.h:22
Main namespace for Lagrange.
Definition: AABBIGL.h:30
Definition: project.cpp:27
Definition: template.h:79
Definition: template.h:41
Definition: template.h:28