Skip to content
Snippets Groups Projects
Commit 1ef06b04 authored by Nat Goodspeed's avatar Nat Goodspeed
Browse files

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)
(cherry picked from commit 8618e41b3489e321ecd70eb65ec4d9ca7e2f75c6)
parent ee7fc1d1
No related branches found
No related tags found
2 merge requests!3Update to main branch,!2Rebase onto current main branch
...@@ -165,12 +165,27 @@ class LL_COMMON_API LLEventDispatcher ...@@ -165,12 +165,27 @@ class LL_COMMON_API LLEventDispatcher
* When calling this name, pass an LLSD::Array. Each entry in turn will be * When calling this name, pass an LLSD::Array. Each entry in turn will be
* converted to the corresponding parameter type using LLSDParam. * converted to the corresponding parameter type using LLSDParam.
*/ */
<<<<<<< variant A
// enable_if usage per https://stackoverflow.com/a/39913395/5533635 // enable_if usage per https://stackoverflow.com/a/39913395/5533635
template<typename Function, template<typename Function,
typename = typename std::enable_if< typename = typename std::enable_if<
boost::function_types::is_nonmember_callable_builtin<Function>::value boost::function_types::is_nonmember_callable_builtin<Function>::value
>::type> >::type>
void add(const std::string& name, const std::string& desc, Function f); void add(const std::string& name, const std::string& desc, Function f);
>>>>>>> variant B
template<typename Function>
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);
####### Ancestor
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);
======= end
/** /**
* Register a nonstatic class method with arbitrary parameters. * Register a nonstatic class method with arbitrary parameters.
...@@ -189,6 +204,7 @@ class LL_COMMON_API LLEventDispatcher ...@@ -189,6 +204,7 @@ class LL_COMMON_API LLEventDispatcher
* When calling this name, pass an LLSD::Array. Each entry in turn will be * When calling this name, pass an LLSD::Array. Each entry in turn will be
* converted to the corresponding parameter type using LLSDParam. * converted to the corresponding parameter type using LLSDParam.
*/ */
<<<<<<< variant A
template<typename Method, typename InstanceGetter, template<typename Method, typename InstanceGetter,
typename = typename std::enable_if< typename = typename std::enable_if<
boost::function_types::is_member_function_pointer<Method>::value && boost::function_types::is_member_function_pointer<Method>::value &&
...@@ -196,6 +212,24 @@ class LL_COMMON_API LLEventDispatcher ...@@ -196,6 +212,24 @@ class LL_COMMON_API LLEventDispatcher
>::type> >::type>
void add(const std::string& name, const std::string& desc, Method f, void add(const std::string& name, const std::string& desc, Method f,
const InstanceGetter& getter); const InstanceGetter& getter);
>>>>>>> variant B
template<typename Method, typename InstanceGetter>
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);
####### Ancestor
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);
======= end
/** /**
* Register a free function with arbitrary parameters. (This also works * Register a free function with arbitrary parameters. (This also works
...@@ -212,12 +246,31 @@ class LL_COMMON_API LLEventDispatcher ...@@ -212,12 +246,31 @@ class LL_COMMON_API LLEventDispatcher
* an LLSD::Array using LLSDArgsMapper and then convert each entry in turn * an LLSD::Array using LLSDArgsMapper and then convert each entry in turn
* to the corresponding parameter type using LLSDParam. * to the corresponding parameter type using LLSDParam.
*/ */
<<<<<<< variant A
template<typename Function, template<typename Function,
typename = typename std::enable_if< typename = typename std::enable_if<
boost::function_types::is_nonmember_callable_builtin<Function>::value boost::function_types::is_nonmember_callable_builtin<Function>::value
>::type> >::type>
void add(const std::string& name, const std::string& desc, Function f, void add(const std::string& name, const std::string& desc, Function f,
const LLSD& params, const LLSD& defaults=LLSD()); const LLSD& params, const LLSD& defaults=LLSD());
>>>>>>> variant B
template<typename Function>
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());
####### Ancestor
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());
======= end
/** /**
* Register a nonstatic class method with arbitrary parameters. * Register a nonstatic class method with arbitrary parameters.
...@@ -240,6 +293,7 @@ class LL_COMMON_API LLEventDispatcher ...@@ -240,6 +293,7 @@ class LL_COMMON_API LLEventDispatcher
* an LLSD::Array using LLSDArgsMapper and then convert each entry in turn * an LLSD::Array using LLSDArgsMapper and then convert each entry in turn
* to the corresponding parameter type using LLSDParam. * to the corresponding parameter type using LLSDParam.
*/ */
<<<<<<< variant A
template<typename Method, typename InstanceGetter, template<typename Method, typename InstanceGetter,
typename = typename std::enable_if< typename = typename std::enable_if<
boost::function_types::is_member_function_pointer<Method>::value && boost::function_types::is_member_function_pointer<Method>::value &&
...@@ -248,6 +302,28 @@ class LL_COMMON_API LLEventDispatcher ...@@ -248,6 +302,28 @@ class LL_COMMON_API LLEventDispatcher
void add(const std::string& name, const std::string& desc, Method f, void add(const std::string& name, const std::string& desc, Method f,
const InstanceGetter& getter, const LLSD& params, const InstanceGetter& getter, const LLSD& params,
const LLSD& defaults=LLSD()); const LLSD& defaults=LLSD());
>>>>>>> variant B
template<typename Method, typename InstanceGetter>
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());
####### Ancestor
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());
======= end
//@} //@}
...@@ -457,8 +533,18 @@ struct LLEventDispatcher::invoker<Function,To,To> ...@@ -457,8 +533,18 @@ struct LLEventDispatcher::invoker<Function,To,To>
} }
}; };
<<<<<<< variant A
template<typename Function, typename> template<typename Function, typename>
void LLEventDispatcher::add(const std::string& name, const std::string& desc, Function f) void LLEventDispatcher::add(const std::string& name, const std::string& desc, Function f)
>>>>>>> variant B
template<typename Function>
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)
####### Ancestor
template<typename Function>
typename boost::enable_if< boost::function_types::is_nonmember_callable_builtin<Function> >::type
LLEventDispatcher::add(const std::string& name, const std::string& desc, Function f)
======= end
{ {
// Construct an invoker_function, a callable accepting const args_source&. // Construct an invoker_function, a callable accepting const args_source&.
// Add to DispatchMap an ArrayParamsDispatchEntry that will handle the // Add to DispatchMap an ArrayParamsDispatchEntry that will handle the
...@@ -467,9 +553,25 @@ void LLEventDispatcher::add(const std::string& name, const std::string& desc, Fu ...@@ -467,9 +553,25 @@ void LLEventDispatcher::add(const std::string& name, const std::string& desc, Fu
boost::function_types::function_arity<Function>::value); boost::function_types::function_arity<Function>::value);
} }
<<<<<<< variant A
template<typename Method, typename InstanceGetter, typename> template<typename Method, typename InstanceGetter, typename>
void LLEventDispatcher::add(const std::string& name, const std::string& desc, Method f, void LLEventDispatcher::add(const std::string& name, const std::string& desc, Method f,
const InstanceGetter& getter) const InstanceGetter& getter)
>>>>>>> variant B
template<typename Method, typename InstanceGetter>
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)
####### Ancestor
template<typename Method, typename InstanceGetter>
typename boost::enable_if< boost::function_types::is_member_function_pointer<Method> >::type
LLEventDispatcher::add(const std::string& name, const std::string& desc, Method f,
const InstanceGetter& getter)
======= end
{ {
// Subtract 1 from the compile-time arity because the getter takes care of // Subtract 1 from the compile-time arity because the getter takes care of
// the first parameter. We only need (arity - 1) additional arguments. // the first parameter. We only need (arity - 1) additional arguments.
...@@ -477,18 +579,48 @@ void LLEventDispatcher::add(const std::string& name, const std::string& desc, Me ...@@ -477,18 +579,48 @@ void LLEventDispatcher::add(const std::string& name, const std::string& desc, Me
boost::function_types::function_arity<Method>::value - 1); boost::function_types::function_arity<Method>::value - 1);
} }
<<<<<<< variant A
template<typename Function, typename> template<typename Function, typename>
void LLEventDispatcher::add(const std::string& name, const std::string& desc, Function f, void LLEventDispatcher::add(const std::string& name, const std::string& desc, Function f,
const LLSD& params, const LLSD& defaults) const LLSD& params, const LLSD& defaults)
>>>>>>> variant B
template<typename Function>
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)
####### Ancestor
template<typename Function>
typename boost::enable_if< boost::function_types::is_nonmember_callable_builtin<Function> >::type
LLEventDispatcher::add(const std::string& name, const std::string& desc, Function f,
const LLSD& params, const LLSD& defaults)
======= end
{ {
// See comments for previous is_nonmember_callable_builtin add(). // See comments for previous is_nonmember_callable_builtin add().
addMapParamsDispatchEntry(name, desc, make_invoker(f), params, defaults); addMapParamsDispatchEntry(name, desc, make_invoker(f), params, defaults);
} }
<<<<<<< variant A
template<typename Method, typename InstanceGetter, typename> template<typename Method, typename InstanceGetter, typename>
void LLEventDispatcher::add(const std::string& name, const std::string& desc, Method f, void LLEventDispatcher::add(const std::string& name, const std::string& desc, Method f,
const InstanceGetter& getter, const InstanceGetter& getter,
const LLSD& params, const LLSD& defaults) const LLSD& params, const LLSD& defaults)
>>>>>>> variant B
template<typename Method, typename InstanceGetter>
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)
####### Ancestor
template<typename Method, typename InstanceGetter>
typename boost::enable_if< boost::function_types::is_member_function_pointer<Method> >::type
LLEventDispatcher::add(const std::string& name, const std::string& desc, Method f,
const InstanceGetter& getter,
const LLSD& params, const LLSD& defaults)
======= end
{ {
addMapParamsDispatchEntry(name, desc, make_invoker(f, getter), params, defaults); addMapParamsDispatchEntry(name, desc, make_invoker(f, getter), params, defaults);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment