From 2dfaba6e32ef027036378e499d9cb28aa2e6220f Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 4 Dec 2019 15:42:56 -0500
Subject: [PATCH] DRTVWR-494: Add llmake_heap(); update to variadic llmake().

---
 indra/llcommon/llmake.h | 52 ++++++++++++++++++++++-------------------
 1 file changed, 28 insertions(+), 24 deletions(-)

diff --git a/indra/llcommon/llmake.h b/indra/llcommon/llmake.h
index 08744f90fb5..02463d97eac 100644
--- a/indra/llcommon/llmake.h
+++ b/indra/llcommon/llmake.h
@@ -12,10 +12,8 @@
  * 
  *         also relevant:
  *
- *         Template argument deduction for class templates
- *         http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html
- *         was apparently adopted in June 2016? Unclear when compilers will
- *         portably support this, but there is hope.
+ *         Template argument deduction for class templates (C++17)
+ *         https://en.cppreference.com/w/cpp/language/class_template_argument_deduction
  *
  * $LicenseInfo:firstyear=2015&license=viewerlgpl$
  * Copyright (c) 2015, Linden Research, Inc.
@@ -25,37 +23,43 @@
 #if ! defined(LL_LLMAKE_H)
 #define LL_LLMAKE_H
 
-/*==========================================================================*|
-// When we allow ourselves to compile with C++11 features enabled, this form
-// should generically handle an arbitrary number of arguments.
-
+/**
+ * Usage: llmake<SomeTemplate>(args...)
+ *
+ * Deduces the types T... of 'args' and returns an instance of
+ * SomeTemplate<T...>(args...).
+ */
 template <template<typename...> class CLASS_TEMPLATE, typename... ARGS>
 CLASS_TEMPLATE<ARGS...> llmake(ARGS && ... args)
 {
     return CLASS_TEMPLATE<ARGS...>(std::forward<ARGS>(args)...);
 }
-|*==========================================================================*/
 
-// As of 2015-12-18, this is what we'll use instead. Add explicit overloads
-// for different numbers of template parameters as use cases arise.
+/// dumb pointer template just in case that's what's wanted
+template <typename T>
+using dumb_pointer = T*;
 
 /**
- * Usage: llmake<SomeTemplate>(arg)
+ * Same as llmake(), but returns a pointer to a new heap instance of
+ * SomeTemplate<T...>(args...) using the pointer of your choice.
  *
- * Deduces the type T of 'arg' and returns an instance of SomeTemplate<T>
- * initialized with 'arg'. Assumes a constructor accepting T (by value,
- * reference or whatever).
+ * @code
+ * auto* dumb  = llmake_heap<SomeTemplate>(args...);
+ * auto shared = llmake_heap<SomeTemplate, std::shared_ptr>(args...);
+ * auto unique = llmake_heap<SomeTemplate, std::unique_ptr>(args...);
+ * @endcode
  */
-template <template<typename> class CLASS_TEMPLATE, typename ARG1>
-CLASS_TEMPLATE<ARG1> llmake(const ARG1& arg1)
-{
-    return CLASS_TEMPLATE<ARG1>(arg1);
-}
-
-template <template<typename, typename> class CLASS_TEMPLATE, typename ARG1, typename ARG2>
-CLASS_TEMPLATE<ARG1, ARG2> llmake(const ARG1& arg1, const ARG2& arg2)
+// POINTER_TEMPLATE is characterized as template<typename...> rather than as
+// template<typename T> because (e.g.) std::unique_ptr has multiple template
+// arguments. Even though we only engage one, std::unique_ptr doesn't match a
+// template template parameter that itself takes only one template parameter.
+template <template<typename...> class CLASS_TEMPLATE,
+          template<typename...> class POINTER_TEMPLATE=dumb_pointer,
+          typename... ARGS>
+POINTER_TEMPLATE<CLASS_TEMPLATE<ARGS...>> llmake_heap(ARGS&&... args)
 {
-    return CLASS_TEMPLATE<ARG1, ARG2>(arg1, arg2);
+    return POINTER_TEMPLATE<CLASS_TEMPLATE<ARGS...>>(
+        new CLASS_TEMPLATE<ARGS...>(std::forward<ARGS>(args)...));
 }
 
 #endif /* ! defined(LL_LLMAKE_H) */
-- 
GitLab