| Message ID | 20250421153556.171192-4-barnabas.pocze@ideasonboard.com |
|---|---|
| State | Superseded |
| Headers | show |
| Series |
|
| Related | show |
Hi Barnabás On Mon, Apr 21, 2025 at 05:35:54PM +0200, Barnabás Pőcze wrote: > Implement a move constructor and move assignment operator for `ControlValue`. > The `ControlValue` type already has an "empty" state that is used when > creating a default constructed `ControlValue`, so have the moved-from > instance return to that state after move construction/assignment. > > This is useful, for example, for `std::vector` as most implementations will > use the copy constructor when reallocating if no nothrow move constructor > is available. Having a nothrow move constructor avoids the extra copies. > It is also useful when using temporaries of `ControlValue` with other > containers such as `std::optional`, and it also makes `ControlInfo` > "cheaply" move constructible/assignable. > > Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> > --- > include/libcamera/controls.h | 26 ++++++++++++++++++++++++++ > src/libcamera/controls.cpp | 18 ++++++++++++++++++ > 2 files changed, 44 insertions(+) > > diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h > index 3f3580036..866d667c4 100644 > --- a/include/libcamera/controls.h > +++ b/include/libcamera/controls.h > @@ -14,6 +14,7 @@ > #include <stdint.h> > #include <string> > #include <unordered_map> > +#include <utility> > #include <vector> > > #include <libcamera/base/class.h> > @@ -165,6 +166,31 @@ public: > ControlValue(const ControlValue &other); > ControlValue &operator=(const ControlValue &other); > > + ControlValue(ControlValue &&other) noexcept > + : type_(other.type_), Is it necessary to reset the other's type to ControlTypeNone ? > + isArray_(std::exchange(other.isArray_, false)), > + numElements_(std::exchange(other.numElements_, 0)), > + storage_(std::exchange(other.storage_, {})) > + { > + other.type_ = ControlTypeNone; > + } > + > + ControlValue &operator=(ControlValue &&other) noexcept > + { > + if (this != &other) { > + release(); > + > + type_ = other.type_; > + isArray_ = std::exchange(other.isArray_, false); > + numElements_ = std::exchange(other.numElements_, 0); > + storage_ = std::exchange(other.storage_, {}); > + > + other.type_ = ControlTypeNone; > + } > + > + return *this; > + } > + > ControlType type() const { return type_; } > bool isNone() const { return type_ == ControlTypeNone; } > bool isArray() const { return isArray_; } > diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp > index d384e1ef7..135e87613 100644 > --- a/src/libcamera/controls.cpp > +++ b/src/libcamera/controls.cpp > @@ -155,6 +155,24 @@ ControlValue &ControlValue::operator=(const ControlValue &other) > return *this; > } > > +/** > + * \fn ControlValue::ControlValue(ControlValue &&other) noexcept > + * \brief Move constructor for ControlValue > + * \param[in] other The ControlValue object to move from > + * > + * Move constructs a ControlValue instance from \a other. > + * After this operation \a other will be in the same state > + * as a default constructed ControlValue instance. > + */ > + > +/** > + * \fn ControlValue &ControlValue::operator=(ControlValue &&other) noexcept > + * \brief Move assignment operator for ControlValue > + * \param[in] other The ControlValue object to move from > + * > + * \sa ControlValue::ControlValue(ControlValue &&other) > + */ > + > /** > * \fn ControlValue::type() > * \brief Retrieve the data type of the value > -- > 2.49.0 >
2025. 11. 21. 12:47 keltezéssel, Jacopo Mondi írta: > Hi Barnabás > > On Mon, Apr 21, 2025 at 05:35:54PM +0200, Barnabás Pőcze wrote: >> Implement a move constructor and move assignment operator for `ControlValue`. >> The `ControlValue` type already has an "empty" state that is used when >> creating a default constructed `ControlValue`, so have the moved-from >> instance return to that state after move construction/assignment. >> >> This is useful, for example, for `std::vector` as most implementations will >> use the copy constructor when reallocating if no nothrow move constructor >> is available. Having a nothrow move constructor avoids the extra copies. >> It is also useful when using temporaries of `ControlValue` with other >> containers such as `std::optional`, and it also makes `ControlInfo` >> "cheaply" move constructible/assignable. >> >> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> >> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> >> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> >> --- >> include/libcamera/controls.h | 26 ++++++++++++++++++++++++++ >> src/libcamera/controls.cpp | 18 ++++++++++++++++++ >> 2 files changed, 44 insertions(+) >> >> diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h >> index 3f3580036..866d667c4 100644 >> --- a/include/libcamera/controls.h >> +++ b/include/libcamera/controls.h >> @@ -14,6 +14,7 @@ >> #include <stdint.h> >> #include <string> >> #include <unordered_map> >> +#include <utility> >> #include <vector> >> >> #include <libcamera/base/class.h> >> @@ -165,6 +166,31 @@ public: >> ControlValue(const ControlValue &other); >> ControlValue &operator=(const ControlValue &other); >> >> + ControlValue(ControlValue &&other) noexcept >> + : type_(other.type_), > > Is it necessary to reset the other's type to ControlTypeNone ? I think so. Since the underlying storage is moved, the previous type cannot always be kept because there would no longer be storage (e.g. if it is a bigger array). So setting it to none unconditionally seems the best decision to me. > >> + isArray_(std::exchange(other.isArray_, false)), >> + numElements_(std::exchange(other.numElements_, 0)), >> + storage_(std::exchange(other.storage_, {})) >> + { >> + other.type_ = ControlTypeNone; >> + } >> + >> + ControlValue &operator=(ControlValue &&other) noexcept >> + { >> + if (this != &other) { >> + release(); >> + >> + type_ = other.type_; >> + isArray_ = std::exchange(other.isArray_, false); >> + numElements_ = std::exchange(other.numElements_, 0); >> + storage_ = std::exchange(other.storage_, {}); >> + >> + other.type_ = ControlTypeNone; >> + } >> + >> + return *this; >> + } >> + >> ControlType type() const { return type_; } >> bool isNone() const { return type_ == ControlTypeNone; } >> bool isArray() const { return isArray_; } >> diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp >> index d384e1ef7..135e87613 100644 >> --- a/src/libcamera/controls.cpp >> +++ b/src/libcamera/controls.cpp >> @@ -155,6 +155,24 @@ ControlValue &ControlValue::operator=(const ControlValue &other) >> return *this; >> } >> >> +/** >> + * \fn ControlValue::ControlValue(ControlValue &&other) noexcept >> + * \brief Move constructor for ControlValue >> + * \param[in] other The ControlValue object to move from >> + * >> + * Move constructs a ControlValue instance from \a other. >> + * After this operation \a other will be in the same state >> + * as a default constructed ControlValue instance. >> + */ >> + >> +/** >> + * \fn ControlValue &ControlValue::operator=(ControlValue &&other) noexcept >> + * \brief Move assignment operator for ControlValue >> + * \param[in] other The ControlValue object to move from >> + * >> + * \sa ControlValue::ControlValue(ControlValue &&other) >> + */ >> + >> /** >> * \fn ControlValue::type() >> * \brief Retrieve the data type of the value >> -- >> 2.49.0 >>
Hi Barnabás, Thank you for the patch. On Mon, Apr 21, 2025 at 05:35:54PM +0200, Barnabás Pőcze wrote: > Implement a move constructor and move assignment operator for `ControlValue`. > The `ControlValue` type already has an "empty" state that is used when > creating a default constructed `ControlValue`, so have the moved-from > instance return to that state after move construction/assignment. > > This is useful, for example, for `std::vector` as most implementations will > use the copy constructor when reallocating if no nothrow move constructor > is available. Having a nothrow move constructor avoids the extra copies. > It is also useful when using temporaries of `ControlValue` with other > containers such as `std::optional`, and it also makes `ControlInfo` > "cheaply" move constructible/assignable. > > Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> > --- > include/libcamera/controls.h | 26 ++++++++++++++++++++++++++ > src/libcamera/controls.cpp | 18 ++++++++++++++++++ > 2 files changed, 44 insertions(+) > > diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h > index 3f3580036..866d667c4 100644 > --- a/include/libcamera/controls.h > +++ b/include/libcamera/controls.h > @@ -14,6 +14,7 @@ > #include <stdint.h> > #include <string> > #include <unordered_map> > +#include <utility> > #include <vector> > > #include <libcamera/base/class.h> > @@ -165,6 +166,31 @@ public: > ControlValue(const ControlValue &other); > ControlValue &operator=(const ControlValue &other); > > + ControlValue(ControlValue &&other) noexcept > + : type_(other.type_), > + isArray_(std::exchange(other.isArray_, false)), > + numElements_(std::exchange(other.numElements_, 0)), > + storage_(std::exchange(other.storage_, {})) > + { > + other.type_ = ControlTypeNone; > + } > + > + ControlValue &operator=(ControlValue &&other) noexcept > + { > + if (this != &other) { > + release(); > + > + type_ = other.type_; > + isArray_ = std::exchange(other.isArray_, false); > + numElements_ = std::exchange(other.numElements_, 0); > + storage_ = std::exchange(other.storage_, {}); > + > + other.type_ = ControlTypeNone; > + } > + > + return *this; > + } The copy constructor and assignement operator are not inline. Is there a reason to inline the move versions ? Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > + > ControlType type() const { return type_; } > bool isNone() const { return type_ == ControlTypeNone; } > bool isArray() const { return isArray_; } > diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp > index d384e1ef7..135e87613 100644 > --- a/src/libcamera/controls.cpp > +++ b/src/libcamera/controls.cpp > @@ -155,6 +155,24 @@ ControlValue &ControlValue::operator=(const ControlValue &other) > return *this; > } > > +/** > + * \fn ControlValue::ControlValue(ControlValue &&other) noexcept > + * \brief Move constructor for ControlValue > + * \param[in] other The ControlValue object to move from > + * > + * Move constructs a ControlValue instance from \a other. > + * After this operation \a other will be in the same state > + * as a default constructed ControlValue instance. > + */ > + > +/** > + * \fn ControlValue &ControlValue::operator=(ControlValue &&other) noexcept > + * \brief Move assignment operator for ControlValue > + * \param[in] other The ControlValue object to move from > + * > + * \sa ControlValue::ControlValue(ControlValue &&other) > + */ > + > /** > * \fn ControlValue::type() > * \brief Retrieve the data type of the value
2026. 09. 01. 15:37 keltezéssel, Laurent Pinchart írta: > Hi Barnabás, > > Thank you for the patch. > > On Mon, Apr 21, 2025 at 05:35:54PM +0200, Barnabás Pőcze wrote: >> Implement a move constructor and move assignment operator for `ControlValue`. >> The `ControlValue` type already has an "empty" state that is used when >> creating a default constructed `ControlValue`, so have the moved-from >> instance return to that state after move construction/assignment. >> >> This is useful, for example, for `std::vector` as most implementations will >> use the copy constructor when reallocating if no nothrow move constructor >> is available. Having a nothrow move constructor avoids the extra copies. >> It is also useful when using temporaries of `ControlValue` with other >> containers such as `std::optional`, and it also makes `ControlInfo` >> "cheaply" move constructible/assignable. >> >> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> >> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> >> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> >> --- >> include/libcamera/controls.h | 26 ++++++++++++++++++++++++++ >> src/libcamera/controls.cpp | 18 ++++++++++++++++++ >> 2 files changed, 44 insertions(+) >> >> diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h >> index 3f3580036..866d667c4 100644 >> --- a/include/libcamera/controls.h >> +++ b/include/libcamera/controls.h >> @@ -14,6 +14,7 @@ >> #include <stdint.h> >> #include <string> >> #include <unordered_map> >> +#include <utility> >> #include <vector> >> >> #include <libcamera/base/class.h> >> @@ -165,6 +166,31 @@ public: >> ControlValue(const ControlValue &other); >> ControlValue &operator=(const ControlValue &other); >> >> + ControlValue(ControlValue &&other) noexcept >> + : type_(other.type_), >> + isArray_(std::exchange(other.isArray_, false)), >> + numElements_(std::exchange(other.numElements_, 0)), >> + storage_(std::exchange(other.storage_, {})) >> + { >> + other.type_ = ControlTypeNone; >> + } >> + >> + ControlValue &operator=(ControlValue &&other) noexcept >> + { >> + if (this != &other) { >> + release(); >> + >> + type_ = other.type_; >> + isArray_ = std::exchange(other.isArray_, false); >> + numElements_ = std::exchange(other.numElements_, 0); >> + storage_ = std::exchange(other.storage_, {}); >> + >> + other.type_ = ControlTypeNone; >> + } >> + >> + return *this; >> + } > > The copy constructor and assignement operator are not inline. Is there a > reason to inline the move versions ? I think these can be well optimized by the compiler into fairly short machine code, so that consideration made me keep them in the header file. > > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > >> + >> ControlType type() const { return type_; } >> bool isNone() const { return type_ == ControlTypeNone; } >> bool isArray() const { return isArray_; } >> diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp >> index d384e1ef7..135e87613 100644 >> --- a/src/libcamera/controls.cpp >> +++ b/src/libcamera/controls.cpp >> @@ -155,6 +155,24 @@ ControlValue &ControlValue::operator=(const ControlValue &other) >> return *this; >> } >> >> +/** >> + * \fn ControlValue::ControlValue(ControlValue &&other) noexcept >> + * \brief Move constructor for ControlValue >> + * \param[in] other The ControlValue object to move from >> + * >> + * Move constructs a ControlValue instance from \a other. >> + * After this operation \a other will be in the same state >> + * as a default constructed ControlValue instance. >> + */ >> + >> +/** >> + * \fn ControlValue &ControlValue::operator=(ControlValue &&other) noexcept >> + * \brief Move assignment operator for ControlValue >> + * \param[in] other The ControlValue object to move from >> + * >> + * \sa ControlValue::ControlValue(ControlValue &&other) >> + */ >> + >> /** >> * \fn ControlValue::type() >> * \brief Retrieve the data type of the value >
On Wed, Sep 02, 2026 at 02:41:35PM +0200, Barnabás Pőcze wrote: > 2026. 09. 01. 15:37 keltezéssel, Laurent Pinchart írta: > > On Mon, Apr 21, 2025 at 05:35:54PM +0200, Barnabás Pőcze wrote: > >> Implement a move constructor and move assignment operator for `ControlValue`. > >> The `ControlValue` type already has an "empty" state that is used when > >> creating a default constructed `ControlValue`, so have the moved-from > >> instance return to that state after move construction/assignment. > >> > >> This is useful, for example, for `std::vector` as most implementations will > >> use the copy constructor when reallocating if no nothrow move constructor > >> is available. Having a nothrow move constructor avoids the extra copies. > >> It is also useful when using temporaries of `ControlValue` with other > >> containers such as `std::optional`, and it also makes `ControlInfo` > >> "cheaply" move constructible/assignable. > >> > >> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> > >> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > >> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> > >> --- > >> include/libcamera/controls.h | 26 ++++++++++++++++++++++++++ > >> src/libcamera/controls.cpp | 18 ++++++++++++++++++ > >> 2 files changed, 44 insertions(+) > >> > >> diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h > >> index 3f3580036..866d667c4 100644 > >> --- a/include/libcamera/controls.h > >> +++ b/include/libcamera/controls.h > >> @@ -14,6 +14,7 @@ > >> #include <stdint.h> > >> #include <string> > >> #include <unordered_map> > >> +#include <utility> > >> #include <vector> > >> > >> #include <libcamera/base/class.h> > >> @@ -165,6 +166,31 @@ public: > >> ControlValue(const ControlValue &other); > >> ControlValue &operator=(const ControlValue &other); > >> > >> + ControlValue(ControlValue &&other) noexcept > >> + : type_(other.type_), > >> + isArray_(std::exchange(other.isArray_, false)), > >> + numElements_(std::exchange(other.numElements_, 0)), > >> + storage_(std::exchange(other.storage_, {})) > >> + { > >> + other.type_ = ControlTypeNone; > >> + } > >> + > >> + ControlValue &operator=(ControlValue &&other) noexcept > >> + { > >> + if (this != &other) { > >> + release(); > >> + > >> + type_ = other.type_; > >> + isArray_ = std::exchange(other.isArray_, false); > >> + numElements_ = std::exchange(other.numElements_, 0); > >> + storage_ = std::exchange(other.storage_, {}); > >> + > >> + other.type_ = ControlTypeNone; > >> + } > >> + > >> + return *this; > >> + } > > > > The copy constructor and assignement operator are not inline. Is there a > > reason to inline the move versions ? > > I think these can be well optimized by the compiler into fairly short machine code, > so that consideration made me keep them in the header file. Should we inline the copy versions too then ? That can be done separately. > > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > > >> + > >> ControlType type() const { return type_; } > >> bool isNone() const { return type_ == ControlTypeNone; } > >> bool isArray() const { return isArray_; } > >> diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp > >> index d384e1ef7..135e87613 100644 > >> --- a/src/libcamera/controls.cpp > >> +++ b/src/libcamera/controls.cpp > >> @@ -155,6 +155,24 @@ ControlValue &ControlValue::operator=(const ControlValue &other) > >> return *this; > >> } > >> > >> +/** > >> + * \fn ControlValue::ControlValue(ControlValue &&other) noexcept > >> + * \brief Move constructor for ControlValue > >> + * \param[in] other The ControlValue object to move from > >> + * > >> + * Move constructs a ControlValue instance from \a other. > >> + * After this operation \a other will be in the same state > >> + * as a default constructed ControlValue instance. > >> + */ > >> + > >> +/** > >> + * \fn ControlValue &ControlValue::operator=(ControlValue &&other) noexcept > >> + * \brief Move assignment operator for ControlValue > >> + * \param[in] other The ControlValue object to move from > >> + * > >> + * \sa ControlValue::ControlValue(ControlValue &&other) > >> + */ > >> + > >> /** > >> * \fn ControlValue::type() > >> * \brief Retrieve the data type of the value
2026. 09. 02. 15:24 keltezéssel, Laurent Pinchart írta: > On Wed, Sep 02, 2026 at 02:41:35PM +0200, Barnabás Pőcze wrote: >> 2026. 09. 01. 15:37 keltezéssel, Laurent Pinchart írta: >>> On Mon, Apr 21, 2025 at 05:35:54PM +0200, Barnabás Pőcze wrote: >>>> Implement a move constructor and move assignment operator for `ControlValue`. >>>> The `ControlValue` type already has an "empty" state that is used when >>>> creating a default constructed `ControlValue`, so have the moved-from >>>> instance return to that state after move construction/assignment. >>>> >>>> This is useful, for example, for `std::vector` as most implementations will >>>> use the copy constructor when reallocating if no nothrow move constructor >>>> is available. Having a nothrow move constructor avoids the extra copies. >>>> It is also useful when using temporaries of `ControlValue` with other >>>> containers such as `std::optional`, and it also makes `ControlInfo` >>>> "cheaply" move constructible/assignable. >>>> >>>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> >>>> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> >>>> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> >>>> --- >>>> include/libcamera/controls.h | 26 ++++++++++++++++++++++++++ >>>> src/libcamera/controls.cpp | 18 ++++++++++++++++++ >>>> 2 files changed, 44 insertions(+) >>>> >>>> diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h >>>> index 3f3580036..866d667c4 100644 >>>> --- a/include/libcamera/controls.h >>>> +++ b/include/libcamera/controls.h >>>> @@ -14,6 +14,7 @@ >>>> #include <stdint.h> >>>> #include <string> >>>> #include <unordered_map> >>>> +#include <utility> >>>> #include <vector> >>>> >>>> #include <libcamera/base/class.h> >>>> @@ -165,6 +166,31 @@ public: >>>> ControlValue(const ControlValue &other); >>>> ControlValue &operator=(const ControlValue &other); >>>> >>>> + ControlValue(ControlValue &&other) noexcept >>>> + : type_(other.type_), >>>> + isArray_(std::exchange(other.isArray_, false)), >>>> + numElements_(std::exchange(other.numElements_, 0)), >>>> + storage_(std::exchange(other.storage_, {})) >>>> + { >>>> + other.type_ = ControlTypeNone; >>>> + } >>>> + >>>> + ControlValue &operator=(ControlValue &&other) noexcept >>>> + { >>>> + if (this != &other) { >>>> + release(); >>>> + >>>> + type_ = other.type_; >>>> + isArray_ = std::exchange(other.isArray_, false); >>>> + numElements_ = std::exchange(other.numElements_, 0); >>>> + storage_ = std::exchange(other.storage_, {}); >>>> + >>>> + other.type_ = ControlTypeNone; >>>> + } >>>> + >>>> + return *this; >>>> + } >>> >>> The copy constructor and assignement operator are not inline. Is there a >>> reason to inline the move versions ? >> >> I think these can be well optimized by the compiler into fairly short machine code, >> so that consideration made me keep them in the header file. > > Should we inline the copy versions too then ? That can be done > separately. They essentially just call `set()`, so possibly a worthwhile change. > >>> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> >>> >>>> + >>>> ControlType type() const { return type_; } >>>> bool isNone() const { return type_ == ControlTypeNone; } >>>> bool isArray() const { return isArray_; } >>>> diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp >>>> index d384e1ef7..135e87613 100644 >>>> --- a/src/libcamera/controls.cpp >>>> +++ b/src/libcamera/controls.cpp >>>> @@ -155,6 +155,24 @@ ControlValue &ControlValue::operator=(const ControlValue &other) >>>> return *this; >>>> } >>>> >>>> +/** >>>> + * \fn ControlValue::ControlValue(ControlValue &&other) noexcept >>>> + * \brief Move constructor for ControlValue >>>> + * \param[in] other The ControlValue object to move from >>>> + * >>>> + * Move constructs a ControlValue instance from \a other. >>>> + * After this operation \a other will be in the same state >>>> + * as a default constructed ControlValue instance. >>>> + */ >>>> + >>>> +/** >>>> + * \fn ControlValue &ControlValue::operator=(ControlValue &&other) noexcept >>>> + * \brief Move assignment operator for ControlValue >>>> + * \param[in] other The ControlValue object to move from >>>> + * >>>> + * \sa ControlValue::ControlValue(ControlValue &&other) >>>> + */ >>>> + >>>> /** >>>> * \fn ControlValue::type() >>>> * \brief Retrieve the data type of the value >
diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 3f3580036..866d667c4 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -14,6 +14,7 @@ #include <stdint.h> #include <string> #include <unordered_map> +#include <utility> #include <vector> #include <libcamera/base/class.h> @@ -165,6 +166,31 @@ public: ControlValue(const ControlValue &other); ControlValue &operator=(const ControlValue &other); + ControlValue(ControlValue &&other) noexcept + : type_(other.type_), + isArray_(std::exchange(other.isArray_, false)), + numElements_(std::exchange(other.numElements_, 0)), + storage_(std::exchange(other.storage_, {})) + { + other.type_ = ControlTypeNone; + } + + ControlValue &operator=(ControlValue &&other) noexcept + { + if (this != &other) { + release(); + + type_ = other.type_; + isArray_ = std::exchange(other.isArray_, false); + numElements_ = std::exchange(other.numElements_, 0); + storage_ = std::exchange(other.storage_, {}); + + other.type_ = ControlTypeNone; + } + + return *this; + } + ControlType type() const { return type_; } bool isNone() const { return type_ == ControlTypeNone; } bool isArray() const { return isArray_; } diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index d384e1ef7..135e87613 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -155,6 +155,24 @@ ControlValue &ControlValue::operator=(const ControlValue &other) return *this; } +/** + * \fn ControlValue::ControlValue(ControlValue &&other) noexcept + * \brief Move constructor for ControlValue + * \param[in] other The ControlValue object to move from + * + * Move constructs a ControlValue instance from \a other. + * After this operation \a other will be in the same state + * as a default constructed ControlValue instance. + */ + +/** + * \fn ControlValue &ControlValue::operator=(ControlValue &&other) noexcept + * \brief Move assignment operator for ControlValue + * \param[in] other The ControlValue object to move from + * + * \sa ControlValue::ControlValue(ControlValue &&other) + */ + /** * \fn ControlValue::type() * \brief Retrieve the data type of the value