-
Notifications
You must be signed in to change notification settings - Fork 12.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc++] Move out flat_map::iterator
(for reusing it in flat_multimap)
#117445
Open
huixie90
wants to merge
1
commit into
llvm:main
Choose a base branch
from
huixie90:hxie/flat_iterator
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+184
−126
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
llvmbot
added
the
libc++
libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
label
Nov 23, 2024
@llvm/pr-subscribers-libcxx Author: Hui (huixie90) ChangesFull diff: https://github.com/llvm/llvm-project/pull/117445.diff 8 Files Affected:
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 0ae031e5365aef..b37b00165fd6ac 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -358,6 +358,7 @@ set(files
__filesystem/space_info.h
__filesystem/u8path.h
__flat_map/flat_map.h
+ __flat_map/key_value_iterator.h
__flat_map/sorted_unique.h
__format/buffer.h
__format/concepts.h
diff --git a/libcxx/include/__flat_map/flat_map.h b/libcxx/include/__flat_map/flat_map.h
index 58b362ad7a706f..6bc8608ecf1902 100644
--- a/libcxx/include/__flat_map/flat_map.h
+++ b/libcxx/include/__flat_map/flat_map.h
@@ -23,11 +23,11 @@
#include <__algorithm/remove_if.h>
#include <__assert>
#include <__compare/synth_three_way.h>
-#include <__concepts/convertible_to.h>
#include <__concepts/swappable.h>
#include <__config>
#include <__cstddef/byte.h>
#include <__cstddef/ptrdiff_t.h>
+#include <__flat_map/key_value_iterator.h>
#include <__flat_map/sorted_unique.h>
#include <__functional/invoke.h>
#include <__functional/is_transparent.h>
@@ -38,7 +38,6 @@
#include <__iterator/next.h>
#include <__iterator/ranges_iterator_traits.h>
#include <__iterator/reverse_iterator.h>
-#include <__memory/addressof.h>
#include <__memory/allocator_traits.h>
#include <__memory/uses_allocator.h>
#include <__memory/uses_allocator_construction.h>
@@ -57,8 +56,8 @@
#include <__type_traits/is_allocator.h>
#include <__type_traits/is_nothrow_constructible.h>
#include <__type_traits/is_same.h>
-#include <__type_traits/maybe_const.h>
#include <__utility/exception_guard.h>
+#include <__utility/move.h>
#include <__utility/pair.h>
#include <__utility/scope_guard.h>
#include <__vector/vector.h>
@@ -82,8 +81,6 @@ template <class _Key,
class _KeyContainer = vector<_Key>,
class _MappedContainer = vector<_Tp>>
class flat_map {
- template <bool _Const>
- struct __iterator;
template <class, class, class, class, class>
friend class flat_map;
@@ -93,6 +90,9 @@ class flat_map {
static_assert(!is_same_v<_KeyContainer, std::vector<bool>>, "vector<bool> is not a sequence container");
static_assert(!is_same_v<_MappedContainer, std::vector<bool>>, "vector<bool> is not a sequence container");
+ template <bool _Const>
+ using __iterator = __key_value_iterator<flat_map, _KeyContainer, _MappedContainer, _Const>;
+
public:
// types
using key_type = _Key;
@@ -134,123 +134,6 @@ class flat_map {
_LIBCPP_HIDE_FROM_ABI static constexpr bool __is_compare_transparent = __is_transparent_v<_Compare, _Compare>;
- template <bool _Const>
- struct __iterator {
- private:
- using __key_iterator = ranges::iterator_t<const key_container_type>;
- using __mapped_iterator = ranges::iterator_t<__maybe_const<_Const, mapped_container_type>>;
- using __reference = pair<iter_reference_t<__key_iterator>, iter_reference_t<__mapped_iterator>>;
-
- struct __arrow_proxy {
- __reference __ref_;
- _LIBCPP_HIDE_FROM_ABI __reference* operator->() { return std::addressof(__ref_); }
- };
-
- __key_iterator __key_iter_;
- __mapped_iterator __mapped_iter_;
-
- friend flat_map;
-
- public:
- using iterator_concept = random_access_iterator_tag;
- // `flat_map::iterator` only satisfy "Cpp17InputIterator" named requirements, because
- // its `reference` is not a reference type.
- // However, to avoid surprising runtime behaviour when it is used with the
- // Cpp17 algorithms or operations, iterator_category is set to random_access_iterator_tag.
- using iterator_category = random_access_iterator_tag;
- using value_type = flat_map::value_type;
- using difference_type = flat_map::difference_type;
-
- _LIBCPP_HIDE_FROM_ABI __iterator() = default;
-
- _LIBCPP_HIDE_FROM_ABI __iterator(__iterator<!_Const> __i)
- requires _Const && convertible_to<ranges::iterator_t<key_container_type>, __key_iterator> &&
- convertible_to<ranges::iterator_t<mapped_container_type>, __mapped_iterator>
- : __key_iter_(std::move(__i.__key_iter_)), __mapped_iter_(std::move(__i.__mapped_iter_)) {}
-
- _LIBCPP_HIDE_FROM_ABI __iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter)
- : __key_iter_(std::move(__key_iter)), __mapped_iter_(std::move(__mapped_iter)) {}
-
- _LIBCPP_HIDE_FROM_ABI __reference operator*() const { return __reference(*__key_iter_, *__mapped_iter_); }
- _LIBCPP_HIDE_FROM_ABI __arrow_proxy operator->() const { return __arrow_proxy{**this}; }
-
- _LIBCPP_HIDE_FROM_ABI __iterator& operator++() {
- ++__key_iter_;
- ++__mapped_iter_;
- return *this;
- }
-
- _LIBCPP_HIDE_FROM_ABI __iterator operator++(int) {
- __iterator __tmp(*this);
- ++*this;
- return __tmp;
- }
-
- _LIBCPP_HIDE_FROM_ABI __iterator& operator--() {
- --__key_iter_;
- --__mapped_iter_;
- return *this;
- }
-
- _LIBCPP_HIDE_FROM_ABI __iterator operator--(int) {
- __iterator __tmp(*this);
- --*this;
- return __tmp;
- }
-
- _LIBCPP_HIDE_FROM_ABI __iterator& operator+=(difference_type __x) {
- __key_iter_ += __x;
- __mapped_iter_ += __x;
- return *this;
- }
-
- _LIBCPP_HIDE_FROM_ABI __iterator& operator-=(difference_type __x) {
- __key_iter_ -= __x;
- __mapped_iter_ -= __x;
- return *this;
- }
-
- _LIBCPP_HIDE_FROM_ABI __reference operator[](difference_type __n) const { return *(*this + __n); }
-
- _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) {
- return __x.__key_iter_ == __y.__key_iter_;
- }
-
- _LIBCPP_HIDE_FROM_ABI friend bool operator<(const __iterator& __x, const __iterator& __y) {
- return __x.__key_iter_ < __y.__key_iter_;
- }
-
- _LIBCPP_HIDE_FROM_ABI friend bool operator>(const __iterator& __x, const __iterator& __y) { return __y < __x; }
-
- _LIBCPP_HIDE_FROM_ABI friend bool operator<=(const __iterator& __x, const __iterator& __y) { return !(__y < __x); }
-
- _LIBCPP_HIDE_FROM_ABI friend bool operator>=(const __iterator& __x, const __iterator& __y) { return !(__x < __y); }
-
- _LIBCPP_HIDE_FROM_ABI friend auto operator<=>(const __iterator& __x, const __iterator& __y)
- requires three_way_comparable<__key_iterator>
- {
- return __x.__key_iter_ <=> __y.__key_iter_;
- }
-
- _LIBCPP_HIDE_FROM_ABI friend __iterator operator+(const __iterator& __i, difference_type __n) {
- auto __tmp = __i;
- __tmp += __n;
- return __tmp;
- }
-
- _LIBCPP_HIDE_FROM_ABI friend __iterator operator+(difference_type __n, const __iterator& __i) { return __i + __n; }
-
- _LIBCPP_HIDE_FROM_ABI friend __iterator operator-(const __iterator& __i, difference_type __n) {
- auto __tmp = __i;
- __tmp -= __n;
- return __tmp;
- }
-
- _LIBCPP_HIDE_FROM_ABI friend difference_type operator-(const __iterator& __x, const __iterator& __y) {
- return difference_type(__x.__key_iter_ - __y.__key_iter_);
- }
- };
-
public:
// [flat.map.cons], construct/copy/destroy
_LIBCPP_HIDE_FROM_ABI flat_map() noexcept(
@@ -1309,20 +1192,20 @@ template <ranges::input_range _Range,
class = __enable_if_t<!__is_allocator<_Compare>::value && __is_allocator<_Allocator>::value>>
flat_map(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator())
-> flat_map<
- __range_key_type<_Range>,
- __range_mapped_type<_Range>,
- _Compare,
- vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
- vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
+ __range_key_type<_Range>,
+ __range_mapped_type<_Range>,
+ _Compare,
+ vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
+ vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
template <ranges::input_range _Range, class _Allocator, class = __enable_if_t<__is_allocator<_Allocator>::value>>
flat_map(from_range_t, _Range&&, _Allocator)
-> flat_map<
- __range_key_type<_Range>,
- __range_mapped_type<_Range>,
- less<__range_key_type<_Range>>,
- vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
- vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
+ __range_key_type<_Range>,
+ __range_mapped_type<_Range>,
+ less<__range_key_type<_Range>>,
+ vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
+ vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
template <class _Key, class _Tp, class _Compare = less<_Key>>
requires(!__is_allocator<_Compare>::value)
diff --git a/libcxx/include/__flat_map/key_value_iterator.h b/libcxx/include/__flat_map/key_value_iterator.h
new file mode 100644
index 00000000000000..a88ab1bbce32af
--- /dev/null
+++ b/libcxx/include/__flat_map/key_value_iterator.h
@@ -0,0 +1,170 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___FLAT_MAP_KEY_VALUE_ITERATOR_H
+#define _LIBCPP___FLAT_MAP_KEY_VALUE_ITERATOR_H
+
+#include <__compare/three_way_comparable.h>
+#include <__concepts/convertible_to.h>
+#include <__config>
+#include <__iterator/iterator_traits.h>
+#include <__memory/addressof.h>
+#include <__ranges/access.h>
+#include <__type_traits/maybe_const.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 23
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Owner, class _KeyContainer, class _MappedContainer, bool _Const>
+struct __key_value_iterator {
+private:
+ using __key_iterator = ranges::iterator_t<const _KeyContainer>;
+ using __mapped_iterator = ranges::iterator_t<__maybe_const<_Const, _MappedContainer>>;
+ using __reference = pair<iter_reference_t<__key_iterator>, iter_reference_t<__mapped_iterator>>;
+
+ struct __arrow_proxy {
+ __reference __ref_;
+ _LIBCPP_HIDE_FROM_ABI __reference* operator->() { return std::addressof(__ref_); }
+ };
+
+ __key_iterator __key_iter_;
+ __mapped_iterator __mapped_iter_;
+
+ friend _Owner;
+
+ template <class, class, class, bool>
+ friend struct __key_value_iterator;
+
+public:
+ using iterator_concept = random_access_iterator_tag;
+ // `flat_map::iterator` only satisfy "Cpp17InputIterator" named requirements, because
+ // its `reference` is not a reference type.
+ // However, to avoid surprising runtime behaviour when it is used with the
+ // Cpp17 algorithms or operations, iterator_category is set to random_access_iterator_tag.
+ using iterator_category = random_access_iterator_tag;
+ using value_type = typename _Owner::value_type;
+ using difference_type = typename _Owner::difference_type;
+
+ _LIBCPP_HIDE_FROM_ABI __key_value_iterator() = default;
+
+ _LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_value_iterator<_Owner, _KeyContainer, _MappedContainer, !_Const> __i)
+ requires _Const && convertible_to<ranges::iterator_t<_KeyContainer>, __key_iterator> &&
+ convertible_to<ranges::iterator_t<_MappedContainer>, __mapped_iterator>
+ : __key_iter_(std::move(__i.__key_iter_)), __mapped_iter_(std::move(__i.__mapped_iter_)) {}
+
+ _LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter)
+ : __key_iter_(std::move(__key_iter)), __mapped_iter_(std::move(__mapped_iter)) {}
+
+ _LIBCPP_HIDE_FROM_ABI __reference operator*() const { return __reference(*__key_iter_, *__mapped_iter_); }
+ _LIBCPP_HIDE_FROM_ABI __arrow_proxy operator->() const { return __arrow_proxy{**this}; }
+
+ _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator++() {
+ ++__key_iter_;
+ ++__mapped_iter_;
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI __key_value_iterator operator++(int) {
+ __key_value_iterator __tmp(*this);
+ ++*this;
+ return __tmp;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator--() {
+ --__key_iter_;
+ --__mapped_iter_;
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI __key_value_iterator operator--(int) {
+ __key_value_iterator __tmp(*this);
+ --*this;
+ return __tmp;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator+=(difference_type __x) {
+ __key_iter_ += __x;
+ __mapped_iter_ += __x;
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator-=(difference_type __x) {
+ __key_iter_ -= __x;
+ __mapped_iter_ -= __x;
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI __reference operator[](difference_type __n) const { return *(*this + __n); }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool
+ operator==(const __key_value_iterator& __x, const __key_value_iterator& __y) {
+ return __x.__key_iter_ == __y.__key_iter_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend bool operator<(const __key_value_iterator& __x, const __key_value_iterator& __y) {
+ return __x.__key_iter_ < __y.__key_iter_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend bool operator>(const __key_value_iterator& __x, const __key_value_iterator& __y) {
+ return __y < __x;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend bool operator<=(const __key_value_iterator& __x, const __key_value_iterator& __y) {
+ return !(__y < __x);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend bool operator>=(const __key_value_iterator& __x, const __key_value_iterator& __y) {
+ return !(__x < __y);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend auto operator<=>(const __key_value_iterator& __x, const __key_value_iterator& __y)
+ requires three_way_comparable<__key_iterator>
+ {
+ return __x.__key_iter_ <=> __y.__key_iter_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator+(const __key_value_iterator& __i, difference_type __n) {
+ auto __tmp = __i;
+ __tmp += __n;
+ return __tmp;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator+(difference_type __n, const __key_value_iterator& __i) {
+ return __i + __n;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator-(const __key_value_iterator& __i, difference_type __n) {
+ auto __tmp = __i;
+ __tmp -= __n;
+ return __tmp;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend difference_type
+ operator-(const __key_value_iterator& __x, const __key_value_iterator& __y) {
+ return difference_type(__x.__key_iter_ - __y.__key_iter_);
+ }
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER >= 23
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___FLAT_MAP_KEY_VALUE_ITERATOR_H
diff --git a/libcxx/include/flat_map b/libcxx/include/flat_map
index 15d79dd1ddca34..e96af677a7eed9 100644
--- a/libcxx/include/flat_map
+++ b/libcxx/include/flat_map
@@ -40,6 +40,7 @@ namespace std {
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
#include <__flat_map/flat_map.h>
+#include <__flat_map/key_value_iterator.h>
#include <__flat_map/sorted_unique.h>
#include <version>
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 4e06a68c6a6b61..52e13aebc2187c 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -1229,6 +1229,7 @@ module std [system] {
module flat_map {
module flat_map { header "__flat_map/flat_map.h" }
+ module key_value_iterator { header "__flat_map/key_value_iterator.h" }
module sorted_unique { header "__flat_map/sorted_unique.h" }
header "flat_map"
diff --git a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/iter_iter_stability.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/iter_iter_stability.pass.cpp
index 1ce859f6c737ea..14189840ce6605 100644
--- a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/iter_iter_stability.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/iter_iter_stability.pass.cpp
@@ -23,6 +23,7 @@
#include <flat_map>
#include <random>
#include <map>
+#include <vector>
#include "test_macros.h"
diff --git a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.iterators/reverse_iterator.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.iterators/reverse_iterator.pass.cpp
index 09e18986a7e813..fc3949d70745fc 100644
--- a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.iterators/reverse_iterator.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.iterators/reverse_iterator.pass.cpp
@@ -23,7 +23,7 @@
#include <deque>
#include <flat_map>
#include <functional>
-#include <string>
+#include <vector>
#include <iterator>
diff --git a/libcxx/test/std/containers/container.adaptors/flat.map/incomplete_type.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.map/incomplete_type.pass.cpp
index 81c590ba73a157..76461951f0d3d8 100644
--- a/libcxx/test/std/containers/container.adaptors/flat.map/incomplete_type.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/flat.map/incomplete_type.pass.cpp
@@ -14,6 +14,7 @@
// type.
#include <flat_map>
+#include <vector>
struct A {
using Map = std::flat_map<A, A>;
|
You can test this locally with the following command:git-clang-format --diff b0e7383e59a100da60c043fd9aca3484c5ed332f 02ca7a67d7aaa1769b3450e7bdf701c722f8435c --extensions ,cpp,h -- libcxx/include/__flat_map/key_value_iterator.h libcxx/include/__flat_map/flat_map.h libcxx/include/flat_map libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/iter_iter_stability.pass.cpp libcxx/test/std/containers/container.adaptors/flat.map/flat.map.iterators/reverse_iterator.pass.cpp libcxx/test/std/containers/container.adaptors/flat.map/incomplete_type.pass.cpp View the diff from clang-format here.diff --git a/libcxx/include/__flat_map/flat_map.h b/libcxx/include/__flat_map/flat_map.h
index 1d1b16e994..b66bc1cb66 100644
--- a/libcxx/include/__flat_map/flat_map.h
+++ b/libcxx/include/__flat_map/flat_map.h
@@ -1190,7 +1190,7 @@ template <ranges::input_range _Range,
class _Allocator = allocator<byte>,
class = __enable_if_t<!__is_allocator<_Compare>::value && __is_allocator<_Allocator>::value>>
flat_map(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator())
- ->flat_map<
+ -> flat_map<
__range_key_type<_Range>,
__range_mapped_type<_Range>,
_Compare,
@@ -1199,7 +1199,7 @@ flat_map(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator(
template <ranges::input_range _Range, class _Allocator, class = __enable_if_t<__is_allocator<_Allocator>::value>>
flat_map(from_range_t, _Range&&, _Allocator)
- ->flat_map<
+ -> flat_map<
__range_key_type<_Range>,
__range_mapped_type<_Range>,
less<__range_key_type<_Range>>,
|
huixie90
force-pushed
the
hxie/flat_iterator
branch
from
November 23, 2024 19:03
a3dadd6
to
9dc6f16
Compare
huixie90
changed the title
[libc++] Move out (for reusing it in flat_multimap)
[libc++] Move out Nov 23, 2024
flat_map::iterator
(for reusing it in flat_multimap)
huixie90
force-pushed
the
hxie/flat_iterator
branch
from
November 24, 2024 13:41
9dc6f16
to
02ca7a6
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.