summaryrefslogtreecommitdiff
path: root/indra/llcommon/apply.h
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2022-08-22 21:00:42 -0400
committerNat Goodspeed <nat@lindenlab.com>2022-08-22 21:00:42 -0400
commit15d37713b9113a6f70dde48c764df02c76e18cbc (patch)
tree022e150c503fa4f63d47374b89cd13d8446cb566 /indra/llcommon/apply.h
parentc0f709b637d800fe07fb265c8ab6f28080994224 (diff)
DRTVWR-558: Fix builds on macOS 12.5 Monterey.
Always search for python3[.exe] instead of plain 'python'. macOS Monterey no longer bundles Python 2 at all. Explicitly make PYTHON_EXECUTABLE a cached value so if the user edits it in CMakeCache.txt, it won't be overwritten by indra/cmake/Python.cmake. Do NOT set DYLD_LIBRARY_PATH for test executables! That has Bad Effects, as discussed in https://stackoverflow.com/q/73418423/5533635. Instead, create symlinks from build-mumble/sharedlibs/Resources -> Release/Resources and from build-mumble/test/Resources -> ../sharedlibs/Release/Resources. For test executables in sharedlibs/RelWithDebInfo and test/RelWithDebInfo, this supports our dylibs' baked-in load path @executable_path/../Resources. That load path assumes running in a standard app bundle (which the viewer in fact does), but we've been avoiding creating an app bundle for every test program. These symlinks allow us to continue doing that while avoiding DYLD_LIBRARY_PATH. Add indra/llcommon/apply.h. The LL::apply() function and its wrapper macro VAPPLY were very useful in diagnosing the problem. Tweak llleap_test.cpp. This source was modified extensively for diagnostic purposes; these are the small improvements that remain.
Diffstat (limited to 'indra/llcommon/apply.h')
-rw-r--r--indra/llcommon/apply.h68
1 files changed, 66 insertions, 2 deletions
diff --git a/indra/llcommon/apply.h b/indra/llcommon/apply.h
index ef4a8fd68b..7c58d63bc0 100644
--- a/indra/llcommon/apply.h
+++ b/indra/llcommon/apply.h
@@ -12,11 +12,48 @@
#if ! defined(LL_APPLY_H)
#define LL_APPLY_H
+#include <boost/type_traits/function_traits.hpp>
#include <tuple>
namespace LL
{
+/**
+ * USAGE NOTE:
+ * https://stackoverflow.com/a/40523474/5533635
+ *
+ * If you're trying to pass apply() a variadic function, the compiler
+ * complains that it can't deduce the callable type, presumably because it
+ * doesn't know which arity to reify to pass.
+ *
+ * But it works to wrap the variadic function in a generic lambda, e.g.:
+ *
+ * @CODE
+ * LL::apply(
+ * [](auto&&... args)
+ * {
+ * return variadic(std::forward<decltype(args)>(args)...);
+ * },
+ * args);
+ * @ENDCODE
+ *
+ * Presumably this is because there's only one instance of the generic lambda
+ * @em type, with a variadic <tt>operator()()</tt>.
+ *
+ * It's pointless to provide a wrapper @em function that implicitly supplies
+ * the generic lambda. You couldn't pass your variadic function to our wrapper
+ * function, for the same original reason!
+ *
+ * Instead we provide a wrapper @em macro. Sorry, Dr. Stroustrup.
+ */
+#define VAPPLY(FUNC, ARGS) \
+ LL::apply( \
+ [](auto&&... args) \
+ { \
+ return (FUNC)(std::forward<decltype(args)>(args)...); \
+ }, \
+ (ARGS))
+
#if __cplusplus >= 201703L
// C++17 implementation
@@ -34,16 +71,43 @@ auto apply_impl(CALLABLE&& func, TUPLE&& args, std::index_sequence<I...>)
}
template <typename CALLABLE, typename... ARGS>
-auto apply(CALLABLE&& func, std::tuple<ARGS...>&& args)
+auto apply(CALLABLE&& func, const std::tuple<ARGS...>& args)
{
// std::index_sequence_for is the magic sauce here, generating an argument
// pack of indexes for each entry in args. apply_impl() can then pass
// those to std::get() to unpack args into individual arguments.
return apply_impl(std::forward<CALLABLE>(func),
- std::forward<std::tuple<ARGS...>>(args),
+ args,
std::index_sequence_for<ARGS...>{});
}
+// per https://stackoverflow.com/a/57510428/5533635
+template <typename CALLABLE, typename T, size_t SIZE>
+auto apply(CALLABLE&& func, const std::array<T, SIZE>& args)
+{
+ return apply(std::forward<CALLABLE>(func), std::tuple_cat(args));
+}
+
+// per https://stackoverflow.com/a/28411055/5533635
+template <typename CALLABLE, typename T, std::size_t... I>
+auto apply_impl(CALLABLE&& func, const std::vector<T>& args, std::index_sequence<I...>)
+{
+ return apply_impl(std::forward<CALLABLE>(func),
+ std::make_tuple(std::forward<T>(args[I])...),
+ I...);
+}
+
+// this goes beyond C++17 std::apply()
+template <typename CALLABLE, typename T>
+auto apply(CALLABLE&& func, const std::vector<T>& args)
+{
+ constexpr auto arity = boost::function_traits<CALLABLE>::arity;
+ assert(args.size() == arity);
+ return apply_impl(std::forward<CALLABLE>(func),
+ args,
+ std::make_index_sequence<arity>());
+}
+
#endif // C++14
} // namespace LL