From 1a668569d6a5936989f1213805a4adbba398d2f0 Mon Sep 17 00:00:00 2001 From: mhucka Date: Tue, 4 Nov 2025 06:29:03 +0000 Subject: [PATCH 1/2] Fix #935: avoid the need to dealocate an object The problem that lead to the compiler warnings is that `discarded_results` in `ApplyFusedGate` is passed by value to the inner `ApplyFusedGate`. When `std::move(measure_result)` happens inside, it's moving from a stack object into a vector that is also on the stack (because it's a parameter passed by value). Then when the inner `ApplyFusedGate` returns, its copy of `mresults` is destroyed, triggering the warning. The solution used here is to refactor the logic into a separate implementation function that accepts a pointer to the results vector. This pointer can be `nullptr` to explicitly signal that measurement results should be discarded. This change eliminates the temporary `discarded_results` vector. Since the vector is never created, its destructor is never called, and the compiler warning vanishes. This is also faster, as you save the cost of constructing and destructing that temporary vector. --- lib/gate_appl.h | 51 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/lib/gate_appl.h b/lib/gate_appl.h index 8601e6f29..190722949 100644 --- a/lib/gate_appl.h +++ b/lib/gate_appl.h @@ -171,6 +171,37 @@ inline void ApplyFusedGateDagger(const Simulator& simulator, const Gate& gate, } } +/** + * Implementation of the two variants of ApplyFusedGate below. Similar to the + * six-parameter version of ApplyFusedGate, this also has an mresults parameter + * but as a pointer. This pointer can be nullptr to explicitly signal that + * measurement results should be discarded. This approach saves creating a dummy + * results vector that would merely be discarded immediately. For the meanings + * of the parameters, refer to the two functions following this one. + */ +template +inline bool ApplyFusedGateInternal( + const typename Simulator::StateSpace& state_space, + const Simulator& simulator, const Gate& gate, Rgen& rgen, + typename Simulator::State& state, + std::vector* mresults) { + + if (gate.kind == gate::kMeasurement) { + auto measure_result = state_space.Measure(gate.qubits, rgen, state); + if (measure_result.valid) { + if (mresults) { + mresults->push_back(std::move(measure_result)); + } + } else { + return false; + } + } else { + ApplyFusedGate(simulator, gate, state); + } + + return true; +} + /** * Applies the given fused gate to the simulator state. * @param state_space StateSpace object required to perform measurements. @@ -191,18 +222,8 @@ inline bool ApplyFusedGate( const Simulator& simulator, const Gate& gate, Rgen& rgen, typename Simulator::State& state, std::vector& mresults) { - if (gate.kind == gate::kMeasurement) { - auto measure_result = state_space.Measure(gate.qubits, rgen, state); - if (measure_result.valid) { - mresults.push_back(std::move(measure_result)); - } else { - return false; - } - } else { - ApplyFusedGate(simulator, gate, state); - } - - return true; + return ApplyFusedGateInternal( + state_space, simulator, gate, rgen, state, &mresults); } /** @@ -220,10 +241,8 @@ template inline bool ApplyFusedGate(const typename Simulator::StateSpace& state_space, const Simulator& simulator, const Gate& gate, Rgen& rgen, typename Simulator::State& state) { - using MeasurementResult = typename Simulator::StateSpace::MeasurementResult; - std::vector discarded_results; - return ApplyFusedGate( - state_space, simulator, gate, rgen, state, discarded_results); + return ApplyFusedGateInternal( + state_space, simulator, gate, rgen, state, nullptr); } } // namespace qsim From 67cfdae270e0db350c0507c5d0b134d42fce73bf Mon Sep 17 00:00:00 2001 From: mhucka Date: Tue, 4 Nov 2025 18:55:45 +0000 Subject: [PATCH 2/2] Implement better approach from Sergei Sergei provided a better solution; it involves some mild refactoring. Also, he pointed out that there is a second very similar function in the file that should be changed in the same way. --- lib/gate_appl.h | 71 ++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/lib/gate_appl.h b/lib/gate_appl.h index 190722949..bfd3df7cc 100644 --- a/lib/gate_appl.h +++ b/lib/gate_appl.h @@ -118,10 +118,16 @@ template inline bool ApplyGate(const typename Simulator::StateSpace& state_space, const Simulator& simulator, const Gate& gate, Rgen& rgen, typename Simulator::State& state) { - using MeasurementResult = typename Simulator::StateSpace::MeasurementResult; - std::vector discarded_results; - return - ApplyGate(state_space, simulator, gate, rgen, state, discarded_results); + if (gate.kind == gate::kMeasurement) { + auto measure_result = state_space.Measure(gate.qubits, rgen, state); + if (!measure_result.valid) { + return false; + } + } else { + ApplyGate(state_space, simulator, gate); + } + + return true; } /** @@ -171,37 +177,6 @@ inline void ApplyFusedGateDagger(const Simulator& simulator, const Gate& gate, } } -/** - * Implementation of the two variants of ApplyFusedGate below. Similar to the - * six-parameter version of ApplyFusedGate, this also has an mresults parameter - * but as a pointer. This pointer can be nullptr to explicitly signal that - * measurement results should be discarded. This approach saves creating a dummy - * results vector that would merely be discarded immediately. For the meanings - * of the parameters, refer to the two functions following this one. - */ -template -inline bool ApplyFusedGateInternal( - const typename Simulator::StateSpace& state_space, - const Simulator& simulator, const Gate& gate, Rgen& rgen, - typename Simulator::State& state, - std::vector* mresults) { - - if (gate.kind == gate::kMeasurement) { - auto measure_result = state_space.Measure(gate.qubits, rgen, state); - if (measure_result.valid) { - if (mresults) { - mresults->push_back(std::move(measure_result)); - } - } else { - return false; - } - } else { - ApplyFusedGate(simulator, gate, state); - } - - return true; -} - /** * Applies the given fused gate to the simulator state. * @param state_space StateSpace object required to perform measurements. @@ -222,8 +197,18 @@ inline bool ApplyFusedGate( const Simulator& simulator, const Gate& gate, Rgen& rgen, typename Simulator::State& state, std::vector& mresults) { - return ApplyFusedGateInternal( - state_space, simulator, gate, rgen, state, &mresults); + if (gate.kind == gate::kMeasurement) { + auto measure_result = state_space.Measure(gate.qubits, rgen, state); + if (measure_result.valid) { + mresults.push_back(std::move(measure_result)); + } else { + return false; + } + } else { + ApplyFusedGate(simulator, gate, state); + } + + return true; } /** @@ -241,8 +226,16 @@ template inline bool ApplyFusedGate(const typename Simulator::StateSpace& state_space, const Simulator& simulator, const Gate& gate, Rgen& rgen, typename Simulator::State& state) { - return ApplyFusedGateInternal( - state_space, simulator, gate, rgen, state, nullptr); + if (gate.kind == gate::kMeasurement) { + auto measure_result = state_space.Measure(gate.qubits, rgen, state); + if (!measure_result.valid) { + return false; + } + } else { + ApplyFusedGate(simulator, gate, state); + } + + return true; } } // namespace qsim