From dc2e2cd76f387ea6e80787fb94adcbc269cd1f25 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Sat, 18 Jun 2022 11:53:57 -0400
Subject: [PATCH] DRTVWR-564: Add LL::apply(): call function, passing args from
 tuple.

This anticipates C++17's std::apply(), and in fact once we detect C++17, we'll
just use that. But in C++14 we must still provide our own implementation.
---
 indra/llcommon/apply.h | 51 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)
 create mode 100644 indra/llcommon/apply.h

diff --git a/indra/llcommon/apply.h b/indra/llcommon/apply.h
new file mode 100644
index 00000000000..ef4a8fd68bb
--- /dev/null
+++ b/indra/llcommon/apply.h
@@ -0,0 +1,51 @@
+/**
+ * @file   apply.h
+ * @author Nat Goodspeed
+ * @date   2022-06-18
+ * @brief  C++14 version of std::apply()
+ * 
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Copyright (c) 2022, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_APPLY_H)
+#define LL_APPLY_H
+
+#include <tuple>
+
+namespace LL
+{
+
+#if __cplusplus >= 201703L
+
+// C++17 implementation
+using std::apply;
+
+#else // C++14
+
+// Derived from https://stackoverflow.com/a/20441189
+// and https://en.cppreference.com/w/cpp/utility/apply
+template <typename CALLABLE, typename TUPLE, std::size_t... I>
+auto apply_impl(CALLABLE&& func, TUPLE&& args, std::index_sequence<I...>)
+{
+    // call func(unpacked args)
+    return std::forward<CALLABLE>(func)(std::move(std::get<I>(args))...);
+}
+
+template <typename CALLABLE, typename... ARGS>
+auto apply(CALLABLE&& func, 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),
+                      std::index_sequence_for<ARGS...>{});
+}
+
+#endif // C++14
+
+} // namespace LL
+
+#endif /* ! defined(LL_APPLY_H) */
-- 
GitLab