diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2023-01-06 17:04:12 -0500 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2023-07-13 12:47:58 -0400 |
commit | a02ccbf1b81549cd44ff5088c94dbb5fc756fea0 (patch) | |
tree | 723679bbf2a0ab1310f3858e38ebc2184a6bc847 /indra/llcommon | |
parent | 8ac35b626072bd94178861dbbaf7d835354c9765 (diff) |
DRTVWR-558: Support LLStoreListener<LLSD>, add LLCaptureListener.
LLStoreListener<LLSD> didn't work because of an ambiguity problem. Resolve
that by introducing an internal storeTarget() method.
Introduce LLCaptureListener<T> that's both an LLStoreListener and the variable
into which to capture the expected result. Introduce LLVarHolder<T> to contain
the variable, so we can guarantee the actual data member will be fully
constructed by the time we want to pass it to the LLStoreListener base class.
(cherry picked from commit a894703188a7755bb9acb897d6c31ae1af6efce0)
Diffstat (limited to 'indra/llcommon')
-rw-r--r-- | indra/llcommon/lleventfilter.h | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/indra/llcommon/lleventfilter.h b/indra/llcommon/lleventfilter.h index 7613850fb2..1fb41e0297 100644 --- a/indra/llcommon/lleventfilter.h +++ b/indra/llcommon/lleventfilter.h @@ -435,16 +435,61 @@ public: // generic type-appropriate store through mTarget, construct an // LLSDParam<T> and store that, thus engaging LLSDParam's custom // conversions. - mTarget = LLSDParam<T>(llsd::drill(event, mPath)); + storeTarget(LLSDParam<T>(llsd::drill(event, mPath))); return mConsume; } private: + // This method disambiguates LLStoreListener<LLSD>. Directly assigning + // some_LLSD_var = LLSDParam<LLSD>(some_LLSD_value); + // is problematic because the compiler has too many choices: LLSD has + // multiple assignment operator overloads, and LLSDParam<LLSD> has a + // templated conversion operator. But LLSDParam<LLSD> can convert to a + // (const LLSD&) parameter, and LLSD::operator=(const LLSD&) works. + void storeTarget(const T& value) + { + mTarget = value; + } + T& mTarget; const LLSD mPath; const bool mConsume; }; +/** + * LLVarHolder bundles a target variable of the specified type. We use it as a + * base class so the target variable will be fully constructed by the time a + * subclass constructor tries to pass a reference to some other base class. + */ +template <typename T> +struct LLVarHolder +{ + T mVar; +}; + +/** + * LLCaptureListener isa LLStoreListener that bundles the target variable of + * interest. + */ +template <typename T> +class LLCaptureListener: public LLVarHolder<T>, + public LLStoreListener<T> +{ +private: + using holder = LLVarHolder<T>; + using super = LLStoreListener<T>; + +public: + LLCaptureListener(const LLSD& path=LLSD(), bool consume=false): + super(*this, holder::mVar, path, consume) + {} + + void set(T&& newval=T()) { holder::mVar = std::forward<T>(newval); } + + const T& get() const { return holder::mVar; } + operator const T&() { return holder::mVar; } +}; + /***************************************************************************** * LLEventLogProxy *****************************************************************************/ |