From e5465f14ba5c71921fb9debff85be2ccc6f56853 Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Thu, 28 Sep 2023 17:19:12 -0500 Subject: [PATCH] Remove deprecated std::iterator inheritance (#529) Signed-off-by: Michael Carroll --- include/gz/common/EnumIface.hh | 401 +++++++++++++++++---------------- src/EnumIface_TEST.cc | 21 +- 2 files changed, 220 insertions(+), 202 deletions(-) diff --git a/include/gz/common/EnumIface.hh b/include/gz/common/EnumIface.hh index 2b0fe1dd8..4cc494518 100644 --- a/include/gz/common/EnumIface.hh +++ b/include/gz/common/EnumIface.hh @@ -17,6 +17,7 @@ #ifndef GZ_COMMON_ENUMITERATOR_HH_ #define GZ_COMMON_ENUMITERATOR_HH_ +#include #include #include #include @@ -24,220 +25,236 @@ #include #include -namespace gz +namespace gz::common { - namespace common + /// \brief Enum interface. Use this interface to convert an enum to + /// a string, and set an enum from a string. + template + class EnumIface { - /// \brief A macro that allows an enum to have an iterator and string - /// conversion. - /// \param[in] name EnumIface instance name. - /// \param[in] enumType Enum type - /// \param[in] begin Enum value that marks the beginning of the enum - /// values. - /// \param[in] end Enum value that marks the end of the enum values. - /// \param[in] names A vector of strings, one for each enum value. - /// \sa EnumIface - /// \sa EnumIterator - #define GZ_ENUM(name, enumType, begin, end, ...) \ - static gz::common::EnumIface name( \ - begin, end, {__VA_ARGS__}); - - /// \brief Enum interface. Use this interface to convert an enum to - /// a string, and set an enum from a string. - template - class EnumIface + /// \brief Constructor + /// \param[in] _start Starting enum value. + /// \param[in] _end Ending enum value. + /// \param[in] _names Name of each enum value. + public: EnumIface(T _start, T _end, + const std::vector &_names) + : names(_names) { - /// \brief Constructor - /// \param[in] _start Starting enum value. - /// \param[in] _end Ending enum value. - /// \param[in] _names Name of each enum value. - public: EnumIface(T _start, T _end, - const std::vector &_names) - : names(_names) - { - this->range[0] = _start; - this->range[1] = _end; - } - - /// \brief Get the beginning enum value. - /// \return Enum value that marks the beginning of the enum list. - public: T Begin() - { - return range[0]; - } + this->range[0] = _start; + this->range[1] = _end; + } - /// \brief Get the end enum value. - /// \return Enum value that marks the end of the enum list. - public: T End() - { - return range[1]; - } + /// \brief Get the beginning enum value. + /// \return Enum value that marks the beginning of the enum list. + public: T Begin() + { + return range[0]; + } - /// \brief Convert enum value to string. - /// \param[in] _e Enum value to convert. - /// \return String representation of the enum. An empty string is - /// returned if _e is invalid, or the names for the enum have not been - /// set. - public: std::string Str(T const &_e) - { - if (static_cast(_e) < names.size()) - return names[static_cast(_e)]; - else - return ""; - } + /// \brief Get the end enum value. + /// \return Enum value that marks the end of the enum list. + public: T End() + { + return range[1]; + } - /// \brief Set an enum from a string. This function requires a valid - /// string, and an array of names for the enum must exist. - /// \param[in] _str String value to convert to enum value. - /// \param[in] _e Enum variable to set. - /// \sa EnumIterator - public: void Set(T &_e, const std::string &_str) - { - auto begin = std::begin(names); - auto end = std::end(names); - - auto find = std::find(begin, end, _str); - if (find != end) - { - _e = static_cast(std::distance(begin, find)); - } - } + /// \brief Convert enum value to string. + /// \param[in] _e Enum value to convert. + /// \return String representation of the enum. An empty string is + /// returned if _e is invalid, or the names for the enum have not been + /// set. + public: std::string Str(T const &_e) + { + std::string ret; + if (static_cast(_e) < names.size()) + ret = names[static_cast(_e)]; + return ret; + } - /// \internal - /// \brief The beginning and end values. Do not use this directly. - public: T range[2]; - - /// \internal - /// \brief Array of string names for each element in the enum. Do not - /// use this directly. - public: std::vector names; - }; - - /// \brief An iterator over enum types. - /// - /// Example: - /// - /// \verbatim - /// enum MyType - /// { - /// MY_TYPE_BEGIN = 0, - /// TYPE1 = MY_TYPE_BEGIN, - /// TYPE2 = 1, - /// MY_TYPE_END - /// }; - /// - /// GZ_ENUM(myTypeIface, MyType, MY_TYPE_BEGIN, MY_TYPE_END, - /// "TYPE1", - /// "TYPE2", - /// "MY_TYPE_END") - /// - /// int main() - /// { - /// EnumIterator i = MY_TYPE_BEGIN; - /// std::cout << "Type Number[" << *i << "]\n"; - /// std::cout << "Type Name[" << myTypeIface.Str(*i) << "]\n"; - /// i++; - /// std::cout << "Type++ Number[" << *i << "]\n"; - /// std::cout << "Type++ Name[" << myTypeIface.Str(*i) << "]\n"; - /// } - /// \verbatim - template - class EnumIterator - : std::iterator + /// \brief Set an enum from a string. This function requires a valid + /// string, and an array of names for the enum must exist. + /// \param[in] _str String value to convert to enum value. + /// \param[in] _e Enum variable to set. + /// \sa EnumIterator + public: void Set(T &_e, const std::string &_str) { - /// \brief Constructor - public: EnumIterator() - { - } + auto begin = std::begin(names); + auto end = std::end(names); - /// \brief Constructor - /// \param[in] _c Enum value - // cppcheck-suppress noExplicitConstructor - public: EnumIterator(const Enum &_c) : c(_c) + auto find = std::find(begin, end, _str); + if (find != end) { + _e = static_cast(std::distance(begin, find)); } + } - /// \brief Equal operator - /// \param[in] _c Enum value to copy - public: EnumIterator &operator=(const Enum &_c) - { - this->c = _c; - return *this; - } + /// \internal + /// \brief The beginning and end values. Do not use this directly. + public: T range[2]; - /// \brief Prefix increment operator. - /// \return Iterator pointing to the next value in the enum. - public: EnumIterator &operator++() - { - this->c = static_cast(static_cast(this->c) + 1); - return *this; - } + /// \internal + /// \brief Array of string names for each element in the enum. Do not + /// use this directly. + public: std::vector names; + }; - /// \brief Postfix increment operator. - /// \return Iterator pointing to the next value in the enum. - public: EnumIterator operator++(const int) - { - EnumIterator cpy(*this); - ++*this; - return cpy; - } + /// \brief An iterator over enum types. + /// + /// Example: + /// + /// \verbatim + /// enum MyType + /// { + /// MY_TYPE_BEGIN = 0, + /// TYPE1 = MY_TYPE_BEGIN, + /// TYPE2 = 1, + /// MY_TYPE_END + /// }; + /// + /// auto myTypeIface = gzEnum(MY_TYPE_BEGIN, MY_TYPE_END, + /// {"TYPE1", + /// "TYPE2", + /// "MY_TYPE_END"}); + /// + /// int main() + /// { + /// EnumIterator i = MY_TYPE_BEGIN; + /// std::cout << "Type Number[" << *i << "]\n"; + /// std::cout << "Type Name[" << myTypeIface.Str(*i) << "]\n"; + /// i++; + /// std::cout << "Type++ Number[" << *i << "]\n"; + /// std::cout << "Type++ Name[" << myTypeIface.Str(*i) << "]\n"; + /// } + /// \verbatim + template + class EnumIterator + { + public: using iterator_category = std::bidirectional_iterator_tag; + public: using value_type = Enum; + public: using difference_type = std::ptrdiff_t; + public: using pointer = Enum*; + public: using reference = Enum&; - /// \brief Prefix decrement operator - /// \return Iterator pointing to the previous value in the enum - public: EnumIterator &operator--() - { - this->c = static_cast(static_cast(this->c) - 1); - return *this; - } + /// \brief Constructor + public: EnumIterator() = default; - /// \brief Postfix decrement operator - /// \return Iterator pointing to the previous value in the enum - public: EnumIterator operator--(const int) - { - EnumIterator cpy(*this); - --*this; - return cpy; - } + /// \brief Constructor + /// \param[in] _c Enum value + // cppcheck-suppress noExplicitConstructor + public: explicit EnumIterator(const Enum &_c) : c(_c) + { + } - /// \brief Dereference operator - /// \return Value of the iterator - public: Enum operator*() const - { - return c; - } + /// \brief Equal operator + /// \param[in] _c Enum value to copy + public: EnumIterator &operator=(const Enum &_c) + { + this->c = _c; + return *this; + } - /// \brief Get the enum value. - /// \return Value of the iterator - public: Enum Value() const - { - return this->c; - } + /// \brief Prefix increment operator. + /// \return Iterator pointing to the next value in the enum. + public: EnumIterator &operator++() + { + this->c = static_cast(static_cast(this->c) + 1); + return *this; + } + + /// \brief Postfix increment operator. + /// \return Iterator pointing to the next value in the enum. + public: EnumIterator operator++(const int) + { + EnumIterator cpy(*this); + ++*this; + return cpy; + } + + /// \brief Prefix decrement operator + /// \return Iterator pointing to the previous value in the enum + public: EnumIterator &operator--() + { + this->c = static_cast(static_cast(this->c) - 1); + return *this; + } + + /// \brief Postfix decrement operator + /// \return Iterator pointing to the previous value in the enum + public: EnumIterator operator--(const int) + { + EnumIterator cpy(*this); + --*this; + return cpy; + } - /// \brief Enum value - /// Did not use a private data class since this should be the only - /// member value ever used. - private: Enum c; - }; - - /// \brief Equality operator - /// \param[in] _e1 First iterator - /// \param[in] _e1 Second iterator - /// \return True if the two iterators contain equal enum values. - template - bool operator==(EnumIterator _e1, EnumIterator _e2) + /// \brief Dereference operator + /// \return Value of the iterator + public: Enum operator*() const { - return _e1.Value() == _e2.Value(); + return c; } - /// \brief Inequality operator - /// \param[in] _e1 First iterator - /// \param[in] _e1 Second iterator - /// \return True if the two iterators do not contain equal enum values. - template - bool operator!=(EnumIterator _e1, EnumIterator _e2) + /// \brief Get the enum value. + /// \return Value of the iterator + public: Enum Value() const { - return !(_e1 == _e2); + return this->c; } + + /// \brief Enum value + /// Did not use a private data class since this should be the only + /// member value ever used. + private: Enum c; + }; + + /// \brief Equality operator + /// \param[in] _e1 First iterator + /// \param[in] _e1 Second iterator + /// \return True if the two iterators contain equal enum values. + template + bool operator==(EnumIterator _e1, EnumIterator _e2) + { + return _e1.Value() == _e2.Value(); + } + + /// \brief Inequality operator + /// \param[in] _e1 First iterator + /// \param[in] _e1 Second iterator + /// \return True if the two iterators do not contain equal enum values. + template + bool operator!=(EnumIterator _e1, EnumIterator _e2) + { + return !(_e1 == _e2); + } + + /// \brief A template that allows an enum to have an iterator and string + /// conversion. + /// \param[in] begin Enum value that marks the beginning of the enum + /// values. + /// \param[in] end Enum value that marks the end of the enum values. + /// \param[in] names A vector of strings, one for each enum value. + /// \sa EnumIface + /// \sa EnumIterator + template + static constexpr gz::common::EnumIface gzEnum( + T _enumBegin, T _enumEnd, const std::vector &_enumVals) + { + return gz::common::EnumIface(_enumBegin, _enumEnd, _enumVals); } -} -#endif +} // namespace gz::common + + +/// \brief A macro that allows an enum to have an iterator and string +/// conversion. +/// \param[in] name EnumIface instance name. +/// \param[in] enumType Enum type +/// \param[in] begin Enum value that marks the beginning of the enum +/// values. +/// \param[in] end Enum value that marks the end of the enum values. +/// \param[in] names A vector of strings, one for each enum value. +/// \sa EnumIface +/// \sa EnumIterator +#define GZ_ENUM(name, enumType, begin, end, ...) \ +static auto name = gz::common::gzEnum(begin, end, {__VA_ARGS__}); + +#endif // GZ_COMMON_ENUMITERATOR_HH_ diff --git a/src/EnumIface_TEST.cc b/src/EnumIface_TEST.cc index a8a8fd51a..8f21f02c2 100644 --- a/src/EnumIface_TEST.cc +++ b/src/EnumIface_TEST.cc @@ -33,11 +33,12 @@ enum MyType MY_TYPE_END }; -GZ_ENUM(myTypeIface, MyType, MY_TYPE_BEGIN, MY_TYPE_END, - "TYPE1", - "TYPE2", - "MY_TYPE_END" -) +auto myTypeIface = gz::common::gzEnum( + MY_TYPE_BEGIN, MY_TYPE_END, { + "TYPE1", + "TYPE2", + "MY_TYPE_END" +}); ///////////////////////////////////////////////// TEST_F(EnumIfaceTest, StringCoversion) @@ -58,16 +59,16 @@ TEST_F(EnumIfaceTest, StringCoversion) ///////////////////////////////////////////////// TEST_F(EnumIfaceTest, Iterator) { - common::EnumIterator end = MY_TYPE_END; + common::EnumIterator end {MY_TYPE_END}; ASSERT_EQ(end.Value(), MY_TYPE_END); - common::EnumIterator begin = MY_TYPE_BEGIN; + common::EnumIterator begin {MY_TYPE_BEGIN}; ASSERT_EQ(*begin, MY_TYPE_BEGIN); int i = 0; // Prefix ++ operator - for (common::EnumIterator typeIter = MY_TYPE_BEGIN; + for (common::EnumIterator typeIter {MY_TYPE_BEGIN}; typeIter != end; ++typeIter, ++i) { ASSERT_EQ(*typeIter, i); @@ -79,7 +80,7 @@ TEST_F(EnumIfaceTest, Iterator) // Postfix ++ operator i = 0; - for (common::EnumIterator typeIter = MY_TYPE_BEGIN; + for (common::EnumIterator typeIter {MY_TYPE_BEGIN}; typeIter != end; ++typeIter, ++i) { ASSERT_EQ(typeIter.Value(), i); @@ -103,7 +104,7 @@ TEST_F(EnumIfaceTest, Iterator) // Postfix -- operator i = MY_TYPE_END - 1; - common::EnumIterator end2 = MY_TYPE_END; + common::EnumIterator end2{MY_TYPE_END}; for (common::EnumIterator typeIter = --end2; typeIter != begin; --typeIter, --i) {