summaryrefslogtreecommitdiff
path: root/indra/llcommon/lleventdispatcher.h
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2022-04-06 21:49:03 -0400
committerNat Goodspeed <nat@lindenlab.com>2022-06-15 20:04:34 -0400
commitf134eace911eca8a231a7c1d556d7d891e8b21ca (patch)
tree0ef5a9c14f9854fe0720cbc0f518a7494e706e49 /indra/llcommon/lleventdispatcher.h
parentb26e516d2b93a442d09f5c3b1b4d8d60139c42f5 (diff)
DRTVWR-558: LLEventAPI allows all LLEventDispatcher add() overloads.
Previously, LLEventAPI intentionally hid all but one of the many add() overloads supported by its LLEventDispatcher base class. The reason was that certain of the add() methods take an optional fourth parameter that's an LLSD::Map describing the expected parameter structure, while others take a fourth templated parameter that's an instance getter callable. This led to ambiguity, especially when passed an LLSDMap instance that's convertible to LLSD but isn't literally LLSD. At the time, it was simpler to constrain the add() methods inherited from LLEventDispatcher. But by adding new std::enable_if constraints to certain LLEventDispatcher add() methods, we've resolved the ambiguities, so LLEventAPI subclasses can now use any add() overload (as claimed on the relevant Confluence page). LLEventDispatcher comments have always loftily claimed that an instance getter callable may return either a pointer or a reference, doesn't matter. But it does when trying to pass the getter's result to boost::fusion::push_back(): a reference must be wrapped with std::ref() while a pointer cannot be. std::ref(pointer) produces errors. Introduce LLEventDispatcher::invoker:: bindable() overloads to Do The Right Thing whether passed a pointer or a reference. (cherry picked from commit 743f487c2e123171c9fc6d5b84d768f1d856d569)
Diffstat (limited to 'indra/llcommon/lleventdispatcher.h')
-rw-r--r--indra/llcommon/lleventdispatcher.h89
1 files changed, 61 insertions, 28 deletions
diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h
index b78c77f8b3..f1e4fe2df7 100644
--- a/indra/llcommon/lleventdispatcher.h
+++ b/indra/llcommon/lleventdispatcher.h
@@ -61,7 +61,6 @@ static const auto& nil(nil_);
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/iterator/transform_iterator.hpp>
-#include <boost/utility/enable_if.hpp>
#include <boost/function_types/is_nonmember_callable_builtin.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/function_arity.hpp>
@@ -167,10 +166,11 @@ public:
* converted to the corresponding parameter type using LLSDParam.
*/
template<typename Function>
- typename boost::enable_if< boost::function_types::is_nonmember_callable_builtin<Function>
- >::type add(const std::string& name,
- const std::string& desc,
- Function f);
+ typename std::enable_if<
+ boost::function_types::is_nonmember_callable_builtin<Function>::value
+ >::type add(const std::string& name,
+ const std::string& desc,
+ Function f);
/**
* Register a nonstatic class method with arbitrary parameters.
@@ -190,11 +190,14 @@ public:
* converted to the corresponding parameter type using LLSDParam.
*/
template<typename Method, typename InstanceGetter>
- typename boost::enable_if< boost::function_types::is_member_function_pointer<Method>
- >::type add(const std::string& name,
- const std::string& desc,
- Method f,
- const InstanceGetter& getter);
+ typename std::enable_if<
+ boost::function_types::is_member_function_pointer<Method>::value &&
+ ! std::is_same<InstanceGetter, LLSD>::value &&
+ ! std::is_same<InstanceGetter, LLSDMap>::value
+ >::type add(const std::string& name,
+ const std::string& desc,
+ Method f,
+ const InstanceGetter& getter);
/**
* Register a free function with arbitrary parameters. (This also works
@@ -212,12 +215,13 @@ public:
* to the corresponding parameter type using LLSDParam.
*/
template<typename Function>
- typename boost::enable_if< boost::function_types::is_nonmember_callable_builtin<Function>
- >::type add(const std::string& name,
- const std::string& desc,
- Function f,
- const LLSD& params,
- const LLSD& defaults=LLSD());
+ typename std::enable_if<
+ boost::function_types::is_nonmember_callable_builtin<Function>::value
+ >::type add(const std::string& name,
+ const std::string& desc,
+ Function f,
+ const LLSD& params,
+ const LLSD& defaults=LLSD());
/**
* Register a nonstatic class method with arbitrary parameters.
@@ -241,13 +245,16 @@ public:
* to the corresponding parameter type using LLSDParam.
*/
template<typename Method, typename InstanceGetter>
- typename boost::enable_if< boost::function_types::is_member_function_pointer<Method>
- >::type add(const std::string& name,
- const std::string& desc,
- Method f,
- const InstanceGetter& getter,
- const LLSD& params,
- const LLSD& defaults=LLSD());
+ typename std::enable_if<
+ boost::function_types::is_member_function_pointer<Method>::value &&
+ ! std::is_same<InstanceGetter, LLSD>::value &&
+ ! std::is_same<InstanceGetter, LLSDMap>::value
+ >::type add(const std::string& name,
+ const std::string& desc,
+ Method f,
+ const InstanceGetter& getter,
+ const LLSD& params,
+ const LLSD& defaults=LLSD());
//@}
@@ -434,7 +441,25 @@ struct LLEventDispatcher::invoker
// Instead of grabbing the first item from argsrc and making an
// LLSDParam of it, call getter() and pass that as the instance param.
invoker<Function, next_iter_type, To>::apply
- ( func, argsrc, boost::fusion::push_back(boost::fusion::nil(), boost::ref(getter())));
+ ( func, argsrc, boost::fusion::push_back(boost::fusion::nil(), bindable(getter())));
+ }
+
+ template <typename T>
+ static inline
+ auto bindable(T&& value,
+ typename std::enable_if<std::is_pointer<T>::value, bool>::type=true)
+ {
+ // if passed a pointer, just return that pointer
+ return std::forward<T>(value);
+ }
+
+ template <typename T>
+ static inline
+ auto bindable(T&& value,
+ typename std::enable_if<! std::is_pointer<T>::value, bool>::type=true)
+ {
+ // if passed a reference, wrap it for binding
+ return std::ref(std::forward<T>(value));
}
};
@@ -454,7 +479,7 @@ struct LLEventDispatcher::invoker<Function,To,To>
};
template<typename Function>
-typename boost::enable_if< boost::function_types::is_nonmember_callable_builtin<Function> >::type
+typename std::enable_if< boost::function_types::is_nonmember_callable_builtin<Function>::value >::type
LLEventDispatcher::add(const std::string& name, const std::string& desc, Function f)
{
// Construct an invoker_function, a callable accepting const args_source&.
@@ -465,7 +490,11 @@ LLEventDispatcher::add(const std::string& name, const std::string& desc, Functio
}
template<typename Method, typename InstanceGetter>
-typename boost::enable_if< boost::function_types::is_member_function_pointer<Method> >::type
+typename std::enable_if<
+ boost::function_types::is_member_function_pointer<Method>::value &&
+ ! std::is_same<InstanceGetter, LLSD>::value &&
+ ! std::is_same<InstanceGetter, LLSDMap>::value
+>::type
LLEventDispatcher::add(const std::string& name, const std::string& desc, Method f,
const InstanceGetter& getter)
{
@@ -476,7 +505,7 @@ LLEventDispatcher::add(const std::string& name, const std::string& desc, Method
}
template<typename Function>
-typename boost::enable_if< boost::function_types::is_nonmember_callable_builtin<Function> >::type
+typename std::enable_if< boost::function_types::is_nonmember_callable_builtin<Function>::value >::type
LLEventDispatcher::add(const std::string& name, const std::string& desc, Function f,
const LLSD& params, const LLSD& defaults)
{
@@ -485,7 +514,11 @@ LLEventDispatcher::add(const std::string& name, const std::string& desc, Functio
}
template<typename Method, typename InstanceGetter>
-typename boost::enable_if< boost::function_types::is_member_function_pointer<Method> >::type
+typename std::enable_if<
+ boost::function_types::is_member_function_pointer<Method>::value &&
+ ! std::is_same<InstanceGetter, LLSD>::value &&
+ ! std::is_same<InstanceGetter, LLSDMap>::value
+>::type
LLEventDispatcher::add(const std::string& name, const std::string& desc, Method f,
const InstanceGetter& getter,
const LLSD& params, const LLSD& defaults)