ความต้องการของเทมเพลตแลมด้าที่นำมาใช้ใน C ++ 20 คืออะไรเมื่อ C ++ 14 มีแลมด้าทั่วไปอยู่แล้ว


99

แนะนำ lambdas ทั่วไปที่ทำให้สามารถเขียนต่อไปนี้:

auto func = [](auto a, auto b){
    return a + b;
};
auto Foo = func(2, 5);
auto Bar = func("hello", "world");

เป็นที่ชัดเจนมากว่าแลมบ์ดาทั่วไปนี้funcทำงานได้เหมือนกับฟังก์ชันเทมเพลตfuncจะทำงานได้

เหตุใดคณะกรรมการ C ++ จึงตัดสินใจเพิ่มไวยากรณ์เทมเพลตสำหรับ Lamda ทั่วไป


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

ฉันเคยบอกว่านี่เป็นกรณีการใช้งานที่น่าสนใจ
Max Langhof

ดูสิ่งนี้สำหรับการเปรียบเทียบแลม
ด้า

คำตอบ:


115

C ++ 14 lambdas ทั่วไปเป็นวิธีที่ยอดเยี่ยมมากในการสร้าง functor operator ()ที่มีลักษณะดังนี้:

template <class T, class U>
auto operator()(T t, U u) const;

แต่ไม่ใช่แบบนี้:

template <class T>
auto operator()(T t1, T t2) const; // Same type please

หรือไม่เช่นนี้:

template <class T, std::size_t N>
auto operator()(std::array<T, N> const &) const; // Only `std::array` please

หรือไม่เช่นนี้ (แม้ว่าจะใช้งานจริงค่อนข้างยาก):

template <class T>
auto operator()() const; // No deduction

C ++ 14 lambdas ใช้ได้ดี แต่ C ++ 20 ช่วยให้เราใช้งานกรณีเหล่านี้ได้โดยไม่ยุ่งยาก


2
ดีและรัดกุม เพียงแค่เพิ่มสิ่งนี้: ตัวแรก (ประเภทเดียวกัน) สามารถแก้ไขได้(auto a, decltype(a) b)ใน C ++ 14
Sebastian Mach

13
@SebastianMach เกือบ. ด้วยโซลูชันbนั้นจะไม่อนุมานและอาร์กิวเมนต์จะถูกแปลงโดยปริยายเป็นประเภทของaแทน
Quentin

32

เนื่องจากคุณสามารถใช้ templated lambdas ใน C ++ 20 ได้คุณจึง จำกัด ประเภทได้ง่ายกว่านิพจน์ SFINAE:

auto lambda = []<typename T>(std::vector<T> t){};

แลมด้านี้จะใช้ได้เฉพาะกับประเภทเวกเตอร์เท่านั้น


8
เป็นวิธีการconstevalที่เกี่ยวข้องกับไวยากรณ์ใหม่หรือไม่? มันเจ๋งและทั้งหมด แต่ฉันไม่ได้รับความเกี่ยวข้อง
StoryTeller - Unslander Monica

เป็นข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่ C ++ 20 เพิ่มให้กับนิพจน์แลมบ์ดามากกว่าคำตอบสำหรับคำถาม
Antoine Morrier

24

ข้อเสนอที่ได้รับการยอมรับเป็น C ++ 20 มีส่วนแรงจูงใจยาวกับตัวอย่าง หลักฐานของมันคือ:

มีสาเหตุสำคัญบางประการที่ทำให้ไวยากรณ์ปัจจุบันสำหรับการกำหนด lambdas ทั่วไปถือว่าไม่เพียงพอโดยผู้เขียน ความสำคัญของมันคือบางสิ่งที่สามารถทำได้อย่างง่ายดายด้วยเทมเพลตฟังก์ชันปกติจำเป็นต้องมีการกระโดดห่วงจำนวนมากเพื่อทำกับ lambdas ทั่วไปหรือไม่สามารถทำได้เลยผู้เขียนคิดว่า lambdas มีค่าเพียงพอที่ C ++ ควรสนับสนุน เช่นเดียวกับเทมเพลตฟังก์ชันปกติ

ต่อไปนี้เป็นตัวอย่างเล็กน้อย


21

ใหม่ "แม่ไวยากรณ์ที่คุ้นเคย" สำหรับ lambdas แนะนำใน C ++ 20 ทำให้โครงสร้างเช่น  for_types และ  for_range ที่ทำงานและวิธีการอ่านได้มากขึ้นเมื่อเทียบกับ C ++ 17 ทางเลือก

(ที่มา: การทำซ้ำเวลาคอมไพล์ด้วย C ++ 20 lambdas )

สิ่งที่น่าสนใจอีกอย่างที่สามารถทำได้กับ lambdas ทั่วไปทั้ง C ++ 14 และ C ++ 17 คือการเรียกโดยตรง  operator() โดยส่งพารามิเตอร์เทมเพลตอย่างชัดเจน:

C ++ 14:

   auto l = [](auto){ };
   l.template operator()<int>(0);

C ++ 20:

  auto l = []<typename T>(){ };
  l.template operator()<int>();

c ++ 14 ตัวอย่างข้างต้นเป็นเรื่องที่ค่อนข้างไร้ประโยชน์: มีวิธีของหมายถึงประเภทที่ให้แก่ไม่มี  ในร่างกายของแลมบ์ดาโดยไม่ให้การโต้แย้งชื่อและการใช้operator() decltypeนอกจากนี้เราถูกบังคับให้ส่งข้อโต้แย้งแม้ว่าเราอาจไม่ต้องการก็ตาม

ตัวอย่าง C ++ 20 แสดงให้เห็นว่า T สามารถเข้าถึงได้ง่ายในเนื้อความของแลมด้าและตอนนี้แลมบ์ดาว่างเปล่าสามารถเป็นเทมเพลตได้โดยพลการ สิ่งนี้จะเป็นประโยชน์อย่างมากสำหรับการนำโครงสร้างเวลาคอมไพล์ดังกล่าวไปใช้

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