summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2023-01-06 17:04:12 -0500
committerNat Goodspeed <nat@lindenlab.com>2023-07-13 12:47:58 -0400
commita02ccbf1b81549cd44ff5088c94dbb5fc756fea0 (patch)
tree723679bbf2a0ab1310f3858e38ebc2184a6bc847 /indra/llcommon
parent8ac35b626072bd94178861dbbaf7d835354c9765 (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.h47
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
*****************************************************************************/