สำหรับใครก็ตามที่ชอบคำตอบ std::views::iota
ของ Cigien แต่ไม่ทำงานใน C++20 หรือสูงกว่า มันค่อนข้างตรงไปตรงมาที่จะใช้คลาส std::views::iota ="post-tag" title="show questions tag 'c++11'" rel="tag">c++11 หรือสูงกว่า
สิ่งที่ต้องการคือ:
- ประเภท LegacyInputIterator พื้นฐาน (สิ่งที่กำหนด
operator++
และ operator*
) ที่ล้อมค่าอินทิกรัล (เช่น int
)
- คลาสที่มีลักษณะคล้ายช่วงบางคลาสที่มี
begin()
และ end()
ที่ส่งคืนตัววนซ้ำข้างต้น สิ่งนี้จะช่วยให้มันทำงานใน for
ลูปตามช่วง
เวอร์ชันที่เรียบง่ายของสิ่งนี้อาจเป็น:
#include <iterator>
// This is just a class that wraps an 'int' in an iterator abstraction
// Comparisons compare the underlying value, and 'operator++' just
// increments the underlying int
class counting_iterator
{
public:
// basic iterator boilerplate
using iterator_category = std::input_iterator_tag;
using value_type = int;
using reference = int;
using pointer = int*;
using difference_type = std::ptrdiff_t;
// Constructor / assignment
constexpr explicit counting_iterator(int x) : m_value{x}{}
constexpr counting_iterator(const counting_iterator&) = default;
constexpr counting_iterator& operator=(const counting_iterator&) = default;
// "Dereference" (just returns the underlying value)
constexpr reference operator*() const { return m_value; }
constexpr pointer operator->() const { return &m_value; }
// Advancing iterator (just increments the value)
constexpr counting_iterator& operator++() {
m_value++;
return (*this);
}
constexpr counting_iterator operator++(int) {
const auto copy = (*this);
++(*this);
return copy;
}
// Comparison
constexpr bool operator==(const counting_iterator& other) const noexcept {
return m_value == other.m_value;
}
constexpr bool operator!=(const counting_iterator& other) const noexcept {
return m_value != other.m_value;
}
private:
int m_value;
};
// Just a holder type that defines 'begin' and 'end' for
// range-based iteration. This holds the first and last element
// (start and end of the range)
// The begin iterator is made from the first value, and the
// end iterator is made from the second value.
struct iota_range
{
int first;
int last;
constexpr counting_iterator begin() const { return counting_iterator{first}; }
constexpr counting_iterator end() const { return counting_iterator{last}; }
};
// A simple helper function to return the range
// This function isn't strictly necessary, you could just construct
// the 'iota_range' directly
constexpr iota_range iota(int first, int last)
{
return iota_range{first, last};
}
ฉันได้กำหนดไว้ข้างต้นด้วย constexpr
โดยที่รองรับ แต่สำหรับ C++ เวอร์ชันก่อนหน้า เช่น C++11/14 คุณอาจต้องลบ constexpr
โดยที่มันไม่ถูกกฎหมายในเวอร์ชันเหล่านั้นจึงจะทำเช่นนั้นได้
ต้นแบบด้านบนช่วยให้โค้ดต่อไปนี้ทำงานใน pre-C ++ 20:
for (int const i : iota(0, 10))
{
std::cout << i << " "; // ok
i = 42; // error
}
ซึ่งจะสร้างแอสเซมบลีเดียวกันเป็นโซลูชัน C++20 std::views::iota
และโซลูชัน for
-loop แบบคลาสสิก เมื่อปรับให้เหมาะสม
ซึ่งใช้งานได้กับคอมไพเลอร์ที่สอดคล้องกับ C++11 (เช่น คอมไพเลอร์เช่น gcc-4.9.4
) และยังคงสร้าง แอสเซมบลีที่เกือบจะเหมือนกัน เป็นคู่พื้นฐาน for
-loop
หมายเหตุ: ฟังก์ชันตัวช่วย iota
มีไว้สำหรับความเท่าเทียมกันของคุณลักษณะกับโซลูชัน C++20 std::views::iota
เท่านั้น แต่ในความเป็นจริงแล้ว คุณสามารถสร้าง iota_range{...}
ได้โดยตรง แทนที่จะเรียก iota(...)
แบบแรกเป็นเพียงการนำเสนอเส้นทางการอัพเกรดที่ง่ายหากผู้ใช้ต้องการเปลี่ยนไปใช้ C ++ 20 ในอนาคต
person
Human-Compiler
schedule
13.08.2020
while(i_copy = loop()) { }
- person stark   schedule 13.08.2020const int& i_safe = i
. คอมไพเลอร์ของคุณควรลบล้างการเบี่ยงเบนใดๆ - person Brian   schedule 13.08.2020i
เสี่ยงต่อตัวลูปที่เป็นอันตราย - person stark   schedule 13.08.2020i
นั้นไม่ดีใช่ไหม คุณต้องการเข้าถึงi
แบบอ่านอย่างเดียวในลูปหรือไม่ - person cigien   schedule 13.08.2020for({int i=0; i<10; ++i}){
สำหรับเรื่องนี้มาโดยตลอด แต่ก็ไม่เคยมีความกล้าที่จะเสนอเรื่องนี้ต่อคณะกรรมการมาตรฐาน หรือ Bjarne เมื่อเขาทำงานอย่างซื่อสัตย์ที่ Morgan Stanley แน่นอนว่าคำแนะนำของฉันไม่อนุญาตให้คุณเข้าถึงi
ในร่างกายด้วยซ้ำ - person Bathsheba   schedule 13.08.2020const int i
ความไม่แน่นอนของดัชนีจะแสดงเฉพาะเมื่อจำเป็นเท่านั้น และคุณสามารถใช้คีย์เวิร์ดinline
เพื่อทำให้ไม่มีผลกระทบต่อเอาต์พุตที่คอมไพล์แล้ว - person Monty Thibault   schedule 14.08.2020const
ที่จะเริ่มต้นด้วย - person Konrad Rudolph   schedule 16.08.2020ì
ในลูป หากลูปของคุณมีขนาดใหญ่ ก็ควรจะปรับโครงสร้างใหม่ให้เป็นฟังก์ชัน - person Phil1970   schedule 17.08.2020