ฉันจะคืนค่า piped ชั่วคราวไปยังการทำงานแบบ range ได้หรือไม่?


9

สมมติว่าฉันมีgenerate_my_rangeคลาสที่โมเดล a range(โดยเฉพาะคือregular) จากนั้นรหัสต่อไปนี้ถูกต้อง:

auto generate_my_range(int some_param) {    
  auto my_transform_op = [](const auto& x){ return do_sth(x); };
  return my_custom_rng_gen(some_param) | ranges::views::transform(my_transform_op);
}
auto cells = generate_my_range(10) | ranges::to<std::vector>;

มีการmy_custom_rng_gen(some_param)ดำเนินการโดยมูลค่าโดย (ตอนแรก) ประกอบท่อหรือฉันจะมีการอ้างอิงห้อยเมื่อฉันออกจากgenerate_my_rangeขอบเขต?

มันจะเหมือนกันกับการเรียก functionnal ranges::views::transform(my_custom_rng_gen(some_param),my_transform_op)หรือไม่?

มันจะถูกต้องหรือไม่ถ้าฉันใช้การอ้างอิง lvalue เช่น:

auto generate_my_range(int some_param) {
  auto my_transform_op = [](const auto& x){ return do_sth(x); };
  auto tmp_ref = my_custom_rng_gen(some_param);
  return tmp_ref | ranges::views::transform(my_transform_op);
}

หากช่วงถูกใช้โดยค่าสำหรับการดำเนินการเหล่านี้ฉันจะทำอย่างไรถ้าฉันส่งการอ้างอิง lvalue ไปยังคอนเทนเนอร์ ฉันควรใช้ranges::views::all(my_container)รูปแบบหรือไม่


my_custom_rng_gen (some_param) มีการ จำกัด ไว้หรือไม่ คุณหมายถึงสิ่งที่ชอบgodbolt.org/z/aTF8RNโดยไม่ต้องใช้ (5)?
Porsche9II

@ Porsche9II ใช่นี่คือช่วงที่มีขอบเขต สมมติว่าเป็นภาชนะ
Bérenger

คำตอบ:


4

ในไลบรารีช่วงมีการดำเนินการสองประเภท:

  • มุมมองที่ขี้เกียจและต้องการภาชนะที่มีอยู่
  • การกระทำที่กระตือรือร้นและสร้างภาชนะใหม่เป็นผลลัพธ์ (หรือแก้ไขสิ่งที่มีอยู่)

มุมมองมีน้ำหนักเบา คุณผ่านค่าเหล่านั้นและกำหนดให้คอนเทนเนอร์พื้นฐานยังคงใช้ได้และไม่เปลี่ยนแปลง

จากเอกสารrange-v3

มุมมองคือ wrapper ที่มีน้ำหนักเบาซึ่งแสดงมุมมองของลำดับขององค์ประกอบในแบบกำหนดเองโดยไม่ต้องปิดบังหรือคัดลอก จำนวนการดูมีราคาถูกในการสร้างและคัดลอกและมีความหมายอ้างอิงที่ไม่ได้เป็นเจ้าของ

และ:

การดำเนินการใด ๆ ในช่วงข้อมูลพื้นฐานที่ทำให้การวนซ้ำของมันหรือผู้ดูแลระบบนั้นจะทำให้มุมมองใด ๆ ที่อ้างถึงส่วนใดส่วนหนึ่งของช่วงนั้นเป็นโมฆะ

การทำลายของภาชนะบรรจุต้นแบบทำให้การวนซ้ำทั้งหมดไม่ถูกต้อง

ในรหัสของคุณคุณจะ specifially โดยใช้มุมมอง - ranges::views::transformคุณใช้ ท่อเป็นเพียงน้ำตาลเชิงประโยคเพื่อให้ง่ายต่อการเขียนในแบบที่เป็น คุณควรดูสิ่งสุดท้ายในท่อเพื่อดูสิ่งที่คุณผลิต - ในกรณีของคุณมันเป็นมุมมอง

หากไม่มีตัวดำเนินการไปป์ก็อาจมีลักษณะเช่นนี้:

ranges::views::transform(my_custom_rng_gen(some_param), my_transform_op)

หากมีการเปลี่ยนแปลงหลายอย่างเชื่อมโยงกันด้วยวิธีนี้คุณจะเห็นได้ว่ามันน่าเกลียดแค่ไหน

ดังนั้นหากmy_custom_rng_genสร้างคอนเทนเนอร์บางชนิดที่คุณแปลงแล้วส่งคืนคอนเทนเนอร์นั้นจะถูกทำลายและคุณได้ทำการอ้างอิงจากมุมมองของคุณ หากmy_custom_rng_genเป็นอีกมุมมองหนึ่งของคอนเทนเนอร์ที่อยู่นอกขอบเขตเหล่านี้ทุกอย่างก็ใช้ได้

อย่างไรก็ตามคอมไพเลอร์ควรสามารถรับรู้ว่าคุณกำลังใช้มุมมองบนคอนเทนเนอร์ชั่วคราวและกดคุณด้วยข้อผิดพลาดในการรวบรวม

หากคุณต้องการให้ฟังก์ชันของคุณส่งคืนช่วงเป็นคอนเทนเนอร์คุณจะต้อง "ผลลัพธ์" ให้ชัดเจน สำหรับสิ่งนั้นให้ใช้ranges::toโอเปอเรเตอร์ในฟังก์ชั่น


อัปเดต:หากต้องการแสดงความคิดเห็นเพิ่มเติมเกี่ยวกับความคิดเห็นของคุณเพิ่มเติม"เอกสารระบุว่าการเขียนช่วง / การไพพ์ใช้และเก็บมุมมองไว้ที่ไหน"

ไปป์เป็นเพียงน้ำตาล syntactic เพื่อเชื่อมต่อสิ่งต่าง ๆ ในนิพจน์ที่อ่านง่าย ขึ้นอยู่กับวิธีการใช้งานมันอาจจะใช่หรือไม่ใช่คืนมุมมอง มันขึ้นอยู่กับอาร์กิวเมนต์ด้านขวา ในกรณีของคุณมันคือ:

`<some range> | ranges::views::transform(...)`

ดังนั้นผลตอบแทนการแสดงออกสิ่งที่views::transformผลตอบแทน

ตอนนี้โดยการอ่านเอกสารของการแปลง:

ด้านล่างนี้เป็นรายการของ combinators ช่วงสันหลังยาวหรือมุมมองที่ Range-v3 นำเสนอและแจ้งให้ทราบเกี่ยวกับวิธีการใช้งานแต่ละอย่าง

[ ... ]

views::transform

กำหนดช่วงของแหล่งที่มาและฟังก์ชัน unary ให้ส่งคืนช่วงใหม่ที่องค์ประกอบผลลัพธ์แต่ละรายการเป็นผลลัพธ์ของการใช้ฟังก์ชัน unary กับองค์ประกอบแหล่งที่มา

ดังนั้นจึงส่งกลับค่าช่วง แต่เนื่องจากเป็นตัวดำเนินการที่ไม่ได้ใช้งานช่วงที่ส่งคืนจึงเป็นมุมมองที่มีความหมายทั้งหมด


ตกลง. สิ่งที่ลึกลับสำหรับฉันก็คือมันทำงานอย่างไรเมื่อฉันส่งภาชนะไปยังท่อ (เช่นวัตถุช่วงที่สร้างโดยองค์ประกอบ) มันต้องเก็บมุมมองของคอนเทนเนอร์อย่างใด มันทำกับranges::views::all(my_container)? และจะเกิดอะไรขึ้นถ้ามุมมองถูกส่งผ่านไปยังไพพ์ มันรู้หรือไม่ว่ามันถูกส่งผ่านคอนเทนเนอร์หรือมุมมอง? จำเป็นหรือไม่ อย่างไร?
Bérenger

"คอมไพเลอร์ควรจะสามารถรับรู้ว่าคุณกำลังใช้มุมมองบนภาชนะชั่วคราวและตีคุณด้วยข้อผิดพลาดในการรวบรวม" นั่นคือสิ่งที่ฉันคิดเช่นกัน: ถ้าฉันทำอะไรโง่มันหมายถึงสัญญาประเภท (เป็นซ้าย มูลค่า) ไม่เป็นจริง สิ่งที่ต้องการนั้นทำโดย range-v3 แต่ในกรณีนี้ไม่มีปัญหาแน่นอน มันรวบรวมและทำงาน ดังนั้นอาจมีพฤติกรรมที่ไม่ได้กำหนด แต่ไม่ปรากฏขึ้น
Bérenger

my_custom_rng_genเพื่อให้แน่ใจว่าถ้าวิ่งรหัสของคุณถูกต้องโดยอุบัติเหตุหรือถ้าทุกอย่างดีฉันจะต้องดูเนื้อหาของ ท่อและtransformปฏิกิริยาใต้ฝากระโปรงนั้นสำคัญอย่างไร นิพจน์ทั้งหมดใช้ช่วงเป็นอาร์กิวเมนต์ (คอนเทนเนอร์หรือมุมมองไปยังคอนเทนเนอร์บางส่วน) และส่งคืนมุมมองที่แตกต่างไปยังคอนเทนเนอร์นั้น ค่าที่ส่งคืนจะไม่เป็นเจ้าของคอนเทนเนอร์เนื่องจากเป็นมุมมอง
CygnusX1

1

นำมาจากเอกสารrange-v3 :

การดู [... ] มีความหมายอ้างอิงที่ไม่ได้เป็นเจ้าของ

และ

การมีออบเจ็กต์ช่วงเดียวจะอนุญาตให้มีการดำเนินงานตามท่อได้ ในไปป์ไลน์มีการปรับช่วงหรือแปลงอย่างกระตือรือร้นด้วยวิธีใด ๆ ด้วยผลที่ได้ทันทีสำหรับการปรับเปลี่ยนหรือการกลายพันธุ์เพิ่มเติม การปรับตัวขี้เกียจได้รับการจัดการโดยมุมมองและการเปลี่ยนแปลงที่กระตือรือร้นได้รับการจัดการโดยการกระทำ

// taken directly from the the ranges documentation
std::vector<int> const vi{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
using namespace ranges;
auto rng = vi | views::remove_if([](int i){ return i % 2 == 1; })
              | views::transform([](int i){ return std::to_string(i); });
// rng == {"2","4","6","8","10"};

ในรหัสข้างต้น rng เก็บการอ้างอิงไปยังข้อมูลพื้นฐานและฟังก์ชันตัวกรองและการแปลง ไม่ทำงานจนกว่าจะทำซ้ำ rng

เนื่องจากคุณบอกว่าช่วงชั่วคราวนั้นอาจจะคิดว่าเป็นคอนเทนเนอร์ฟังก์ชันของคุณจะคืนค่าการอ้างอิงห้อย

กล่าวอีกนัยหนึ่งคุณต้องตรวจสอบให้แน่ใจว่าช่วงที่อยู่เหนือกว่ามุมมองหรือคุณกำลังมีปัญหา


ใช่มุมมองไม่ได้เป็นเจ้าของ แต่เอกสารบอกว่าการเขียนช่วง / ไพพ์ใช้เวลาที่ไหนและเก็บมุมมองไว้ที่ไหน มันอาจเป็นไปได้ (และฉันคิดว่าเป็นสิ่งที่ดี) ที่จะมีนโยบายดังต่อไปนี้: จัดเก็บตามมูลค่าถ้าช่วงที่กำหนดโดยการอ้างอิงค่า rvalue
Bérenger

1
@ Bérengerฉันได้เพิ่มเอกสารอีกเล็กน้อย แต่ประเด็นก็คือเรื่องจริง: มุมมองที่เป็นที่ไม่ใช่เจ้าของ มันไม่สนใจว่าคุณจะส่งค่า
Rumburak
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.