From a02ccbf1b81549cd44ff5088c94dbb5fc756fea0 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 6 Jan 2023 17:04:12 -0500 Subject: DRTVWR-558: Support LLStoreListener, add LLCaptureListener. LLStoreListener didn't work because of an ambiguity problem. Resolve that by introducing an internal storeTarget() method. Introduce LLCaptureListener that's both an LLStoreListener and the variable into which to capture the expected result. Introduce LLVarHolder 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) --- indra/llcommon/lleventfilter.h | 47 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) 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 and store that, thus engaging LLSDParam's custom // conversions. - mTarget = LLSDParam(llsd::drill(event, mPath)); + storeTarget(LLSDParam(llsd::drill(event, mPath))); return mConsume; } private: + // This method disambiguates LLStoreListener. Directly assigning + // some_LLSD_var = LLSDParam(some_LLSD_value); + // is problematic because the compiler has too many choices: LLSD has + // multiple assignment operator overloads, and LLSDParam has a + // templated conversion operator. But LLSDParam 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 +struct LLVarHolder +{ + T mVar; +}; + +/** + * LLCaptureListener isa LLStoreListener that bundles the target variable of + * interest. + */ +template +class LLCaptureListener: public LLVarHolder, + public LLStoreListener +{ +private: + using holder = LLVarHolder; + using super = LLStoreListener; + +public: + LLCaptureListener(const LLSD& path=LLSD(), bool consume=false): + super(*this, holder::mVar, path, consume) + {} + + void set(T&& newval=T()) { holder::mVar = std::forward(newval); } + + const T& get() const { return holder::mVar; } + operator const T&() { return holder::mVar; } +}; + /***************************************************************************** * LLEventLogProxy *****************************************************************************/ -- cgit v1.2.3