C ++ std: ตัวอย่างใด ๆ

C Std Tawxyang Di



ในการเขียนโปรแกรม C++ “std::any” จาก Standard Template Library (STL) จะแนะนำการพิมพ์แบบไดนามิกเพื่อจัดการกับข้อมูลที่ต่างกัน ต่างจากคอนเทนเนอร์แบบเดิม “std::any” อนุญาตให้จัดเก็บค่าประเภทใดก็ได้ภายในคอนเทนเนอร์เดียว เพิ่มความยืดหยุ่นในสถานการณ์ที่ไม่ทราบประเภทข้อมูลหรือเปลี่ยนแปลง ณ รันไทม์ วิธีการไม่เชื่อเรื่องพระเจ้าประเภทนี้ส่งเสริมการเขียนโปรแกรมทั่วไปซึ่งช่วยให้นักพัฒนาสามารถสร้างโค้ดที่ปรับเปลี่ยนได้และแสดงออกได้มากขึ้นในขณะที่ยังคงรักษาความปลอดภัยของประเภทไว้ ในการสำรวจนี้ เราจะเจาะลึกคุณสมบัติของ “std::any” รูปแบบการใช้งาน และตัวอย่างเชิงปฏิบัติที่แสดงให้เห็นถึงบทบาทในการเขียนโค้ด C++ ที่มีประสิทธิภาพและยืดหยุ่น

ตัวอย่างที่ 1: การใช้งานพื้นฐานของ Std::Any

ขั้นแรก เรามาสำรวจตัวอย่างที่ตรงไปตรงมาเพื่อสาธิตการใช้งานพื้นฐานของ “std::any” พิจารณาสถานการณ์ที่คุณต้องการฟังก์ชันเพื่อยอมรับพารามิเตอร์ประเภทต่างๆ:







นี่คือข้อมูลโค้ด:



#รวม
#รวม <ใดๆ>

กระบวนการเป็นโมฆะใดๆ ( const std::ใด ๆ & ค่า ) {
ถ้า ( ค่าhas_value ( ) ) {
มาตรฐาน::cout << 'ประเภทของมูลค่าที่เก็บไว้:' << ค่า.ประเภท ( ) .ชื่อ ( ) << มาตรฐาน::endl;

ถ้า ( ค่า.ประเภท ( ) == พิมพ์รหัส ( ภายใน ) ) {
มาตรฐาน::cout << 'ค่า: ' << มาตรฐาน::any_cast < ภายใน > ( ค่า ) << มาตรฐาน::endl;
} อื่น ถ้า ( ค่า.ประเภท ( ) == พิมพ์รหัส ( สองเท่า ) ) {
มาตรฐาน::cout << 'ค่า: ' << มาตรฐาน::any_cast < สองเท่า > ( ค่า ) << มาตรฐาน::endl;
} อื่น ถ้า ( ค่า.ประเภท ( ) == พิมพ์รหัส ( มาตรฐาน::string ) ) {
มาตรฐาน::cout << 'ค่า: ' << มาตรฐาน::any_cast < มาตรฐาน::string > ( ค่า ) << มาตรฐาน::endl;
} อื่น {
มาตรฐาน::cout << “ประเภทที่ไม่รองรับ!” << มาตรฐาน::endl;
}
} อื่น {
มาตรฐาน::cout << 'ไม่มีค่าที่เก็บอยู่ใน std::any' << มาตรฐาน::endl;
}
}

int หลัก ( ) {
กระบวนการใดๆ ( 42 ) ;
กระบวนการใดๆ ( 3.14 ) ;
กระบวนการใดๆ ( มาตรฐาน::string ( 'สวัสดี std::any!' ) ) ;
กระบวนการใดๆ ( 4.5ฟ ) ; // ไม่รองรับ พิมพ์

กลับ 0 ;
}


ในตัวอย่างนี้ เรากำหนดฟังก์ชัน 'processAny' ที่ใช้การอ้างอิง 'std::any' เป็นพารามิเตอร์และตรวจสอบเนื้อหา ภายในฟังก์ชัน ก่อนอื่นเราจะตรวจสอบดูว่าตัวแปร “std::any” มีค่าที่เก็บไว้โดยใช้ has_value() หรือไม่ หากมีค่าอยู่ เราจะกำหนดประเภทของค่าที่เก็บไว้โดยใช้ type().name() และดำเนินการพิมพ์ค่าที่เกี่ยวข้องตามประเภทของค่านั้น จากนั้นฟังก์ชันหลักจะสาธิตยูทิลิตีของ “processAny” โดยการเรียกมันด้วยประเภทต่างๆ ได้แก่ จำนวนเต็ม (42) คู่ (3.14) และสตริง (“Hello, std::any!”) ฟังก์ชันนี้จะจัดการแต่ละประเภทอย่างเหมาะสมและพิมพ์ค่าตามลำดับ อย่างไรก็ตาม เมื่อพยายามประมวลผลตัวเลขทศนิยม (4.5f) ซึ่งไม่ได้รับการสนับสนุนในตัวอย่างนี้ โปรแกรมจะจัดการกับสถานการณ์ได้อย่างสวยงามโดยการระบุว่าประเภทนั้นไม่ได้รับการสนับสนุน



ผลลัพธ์ที่สร้างขึ้นคือ:






สิ่งนี้แสดงให้เห็นว่า “std::any” ช่วยให้สามารถจัดการข้อมูลประเภทต่างๆ แบบไดนามิกได้อย่างไร ทำให้เป็นเครื่องมืออเนกประสงค์สำหรับการเขียนโปรแกรมทั่วไปใน C++

ตัวอย่างที่ 2: การจัดเก็บประเภทที่ผู้ใช้กำหนด

ตัวอย่างที่สองสำรวจว่าประเภทไดนามิกนี้ภายใน Standard Template Library (STL) รองรับโครงสร้างข้อมูลที่กำหนดเองได้อย่างไร โดยมุ่งเน้นไปที่ประเภทที่ผู้ใช้กำหนด ซึ่งเป็นโครงสร้างจุด เราจะแสดงให้เห็นว่า “std::any” จัดการกับอินสแตนซ์ของโครงสร้างดังกล่าวอย่างไร



นี่คือรหัส:

#รวม
#รวม <ใดๆ>

คลาส MyClass {
สาธารณะ:
ห้องเรียนของฉัน ( ค่า int ) : ข้อมูล ( ค่า ) { }

เป็นโมฆะ printData ( ) ค่าคงที่ {
มาตรฐาน::cout << 'ข้อมูลใน MyClass:' << ข้อมูล << มาตรฐาน::endl;
}

ส่วนตัว:
ข้อมูลภายใน;
} ;

int หลัก ( ) {
std::anyanyObject = MyClass ( 42 ) ;

ถ้า ( anyObject.has_value ( ) ) {
อัตโนมัติ & myClassInstance = std::any_cast < ห้องเรียนของฉัน &> ( วัตถุใดๆ ) ;
myClassInstance.printData ( ) ;
} อื่น {
มาตรฐาน::cout << 'ไม่มีค่าที่เก็บอยู่ใน std::any' << มาตรฐาน::endl;
}

กลับ 0 ;
}


ในตัวอย่างโค้ด C++ นี้ เราสร้างตัวอย่างง่ายๆ เพื่อแสดงโดยใช้ประเภท “std::any” พร้อมด้วยคลาสที่ผู้ใช้กำหนดที่เรียกว่า “MyClass” ภายในคลาสจะมีตัวแปรสมาชิกส่วนตัวที่เรียกว่า “data” และวิธีการสาธารณะที่เรียกว่า printData() เพื่อแสดงค่าของข้อมูลนี้ ค่าจำนวนเต็มจะถูกส่งผ่านและกำหนดให้กับสมาชิก 'ข้อมูล' ในตัวสร้าง

ในฟังก์ชัน 'main' เราจะสร้างอินสแตนซ์อ็อบเจ็กต์ 'MyClass' ด้วยค่าเริ่มต้น 42 จากนั้นจัดเก็บไว้ในตัวแปร 'std::any' ชื่อ 'anyObject' สิ่งนี้แสดงให้เห็นถึงความสามารถของ “std::any” เพื่อเก็บอินสแตนซ์ของคลาสที่ผู้ใช้กำหนด

ต่อไปนี้ เราใช้คำสั่ง 'if' เพื่อตรวจสอบว่า 'anyObject' มีค่าหรือไม่โดยใช้เมธอด has_value() หากมีค่า เราจะดึงวัตถุที่เก็บไว้โดยใช้ “std::any_cast” “std::any_cast” ใช้กับอาร์กิวเมนต์เทมเพลต “MyClass&” เพื่อส่งวัตถุที่เก็บไว้ไปยังการอ้างอิงของ “MyClass” จากนั้นการอ้างอิงนี้ 'myClassInstance' จะใช้เพื่อเรียกใช้เมธอด printData() ซึ่งแสดงความสามารถในการเข้าถึงและดำเนินการกับประเภทที่ผู้ใช้กำหนดซึ่งเก็บไว้ภายใน 'std::any'

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

นี่คือผลลัพธ์:

ตัวอย่างที่ 3: คอนเทนเนอร์ประเภทผสม

ในการเขียนโปรแกรม “คอนเทนเนอร์แบบผสม” หมายถึงโครงสร้างข้อมูลที่สามารถเก็บองค์ประกอบของประเภทข้อมูลที่หลากหลายและอาจไม่เกี่ยวข้องกัน ความยืดหยุ่นนี้มีประโยชน์เมื่อต้องรับมือกับสถานการณ์ที่ไม่ทราบประเภทข้อมูลในขณะคอมไพล์หรือมีการเปลี่ยนแปลงแบบไดนามิกระหว่างการทำงานของโปรแกรม ในภาษา C++ “std::any” เป็นตัวอย่างแนวคิดนี้ โดยอนุญาตให้สร้างคอนเทนเนอร์เดียวเพื่อเก็บค่าประเภทต่างๆ

มาสำรวจสถานการณ์ที่เราสร้างคอนเทนเนอร์ที่มีประเภทต่างๆ กัน:

#รวม
#รวม <ใดๆ>
#รวม <เวกเตอร์>

int หลัก ( ) {

มาตรฐาน::เวกเตอร์ < มาตรฐาน::ใดก็ได้ > คอนเทนเนอร์ผสม;

mixContainer.push_back ( 42 ) ;
mixContainer.push_back ( 3.14 ) ;
mixContainer.push_back ( มาตรฐาน::string ( 'สวัสดี' ) ) ;
mixContainer.push_back ( จริง ) ;

สำหรับ ( เชื่อมต่ออัตโนมัติ & องค์ประกอบ : mixContainer ) {
ถ้า ( องค์ประกอบ.ประเภท ( ) == พิมพ์รหัส ( ภายใน ) ) {
มาตรฐาน::cout << 'จำนวนเต็ม:' << มาตรฐาน::any_cast < ภายใน > ( องค์ประกอบ ) << มาตรฐาน::endl;
} อื่น ถ้า ( องค์ประกอบ.ประเภท ( ) == พิมพ์รหัส ( สองเท่า ) ) {
มาตรฐาน::cout << 'สองเท่า: ' << มาตรฐาน::any_cast < สองเท่า > ( องค์ประกอบ ) << มาตรฐาน::endl;
} อื่น ถ้า ( องค์ประกอบ.ประเภท ( ) == พิมพ์รหัส ( มาตรฐาน::string ) ) {
มาตรฐาน::cout << 'สตริง:' << มาตรฐาน::any_cast < มาตรฐาน::string > ( องค์ประกอบ ) << มาตรฐาน::endl;
} อื่น ถ้า ( องค์ประกอบ.ประเภท ( ) == พิมพ์รหัส ( บูล ) ) {
มาตรฐาน::cout << 'บูลีน:' << มาตรฐาน::any_cast < บูล > ( องค์ประกอบ ) << มาตรฐาน::endl;
} อื่น {
มาตรฐาน::cout << 'ไม่ทราบประเภท' << มาตรฐาน::endl;
}
}

กลับ 0 ;
}


ในภาพประกอบนี้ เราสาธิตแนวคิดของคอนเทนเนอร์แบบผสมโดยใช้ C++ และฟีเจอร์ “std::any” เราสร้าง “std::vector” ชื่อ “mixedContainer” เพื่อทำหน้าที่เป็นคอนเทนเนอร์ของเราเพื่อเก็บองค์ประกอบของข้อมูลประเภทต่างๆ เมื่อใช้ฟังก์ชัน 'push_back' เราเติมคอนเทนเนอร์นี้ด้วยองค์ประกอบต่างๆ รวมถึงจำนวนเต็ม (42) สองเท่า (3.14) สตริง (“Hello”) และบูลีน (จริง)

เมื่อเราวนซ้ำผ่าน “mixedContainer” โดยใช้ลูป “for” เราจะใช้ฟังก์ชัน type() เพื่อระบุประเภทข้อมูลของแต่ละองค์ประกอบแบบไดนามิก ด้วยการใช้ “std::any_cast” เราแยกและพิมพ์ค่าที่เกี่ยวข้องตามประเภทของค่าเหล่านั้น ตัวอย่างเช่น หากองค์ประกอบเป็นประเภท 'int' เราจะพิมพ์เป็นจำนวนเต็ม หากเป็นประเภท 'double' เราจะพิมพ์เป็น double และอื่นๆ

นี่คือผลลัพธ์ที่สร้างขึ้น:

ตัวอย่างที่ 4: การจัดการข้อผิดพลาดกับ Std::Any

การจัดการข้อผิดพลาดเมื่อใช้ “std::any” เกี่ยวข้องกับการตรวจสอบว่ารองรับประเภทนั้นหรือไม่หรือเก็บค่าไว้หรือไม่ ในตัวอย่างนี้ เราสาธิตวิธีจัดการกับประเภทที่ไม่รองรับ:

#รวม
#รวม <ใดๆ>

int หลัก ( ) {
มาตรฐาน::ใดๆ myAny = 42 ;

พยายาม {

ค่าสองเท่า = std::any_cast < สองเท่า > ( ของฉันอันไหนก็ได้ ) ;
มาตรฐาน::cout << 'ค่า: ' << ค่า << มาตรฐาน::endl;
} จับ ( const มาตรฐาน::bad_any_cast & มันคือ ) {

มาตรฐาน::cerr << 'ข้อผิดพลาด: ' << จ.อะไร ( ) << มาตรฐาน::endl;
}

กลับ 0 ;
}


เราเริ่มต้นด้วยการเริ่มต้นตัวแปร “std::any” “myAny” ด้วยค่า 42 ของประเภทจำนวนเต็ม ภายในบล็อก “ลอง” ที่ตามมา เราจะพยายามแปลงค่าจำนวนเต็มนี้เป็น “สองเท่า” โดยใช้การดำเนินการ “std::any_cast” อย่างไรก็ตาม เนื่องจากประเภทจริงที่จัดเก็บไว้ใน 'myAny' นั้นเป็นจำนวนเต็ม การดำเนินการส่งนี้จึงไม่ถูกต้องสำหรับ 'double' ซึ่งทำให้ประเภทไม่ตรงกัน

เพื่อจัดการข้อผิดพลาดที่อาจเกิดขึ้นนี้อย่างสวยงาม เราใช้การจัดการข้อยกเว้นด้วยบล็อก 'catch' ที่ออกแบบมาเพื่อตรวจจับประเภทข้อยกเว้นเฉพาะของ 'std::bad_any_cast' ในกรณีที่ส่งไม่สำเร็จ บล็อก 'catch' จะถูกเปิดใช้งานและเราสร้างข้อความแสดงข้อผิดพลาดโดยใช้ 'std::cerr' เพื่อสื่อสารลักษณะของข้อผิดพลาด กลยุทธ์การจัดการข้อผิดพลาดนี้ช่วยให้มั่นใจได้ว่าโปรแกรมของเราสามารถจัดการกับสถานการณ์ที่ประเภทที่พยายามสร้างขัดแย้งกับประเภทจริงที่จัดเก็บไว้ในตัวแปร “std::any” ได้อย่างสวยงาม

บทสรุป

ในบทความนี้ เราได้สำรวจการใช้งานของ “std::any” ใน C++ ซึ่งเป็นคอนเทนเนอร์ประเภทไดนามิกที่นำมาใช้ใน C++ สำหรับค่าประเภทต่างๆ เราแสดงให้เห็นถึงความเก่งกาจของมันผ่านตัวอย่างต่างๆ โดยจัดแสดงสถานการณ์ต่างๆ ตั้งแต่การใช้งานขั้นพื้นฐานไปจนถึงการจัดการประเภทที่ผู้ใช้กำหนดและคอลเลกชันที่แตกต่างกัน เราได้สาธิตการใช้งานจริงในสถานการณ์ที่ไม่ทราบประเภทของข้อมูลในขณะรวบรวม นอกจากนี้ เรายังสำรวจเกี่ยวกับเทคนิคการจัดการข้อผิดพลาด โดยเน้นถึงความสำคัญของการจัดการประเภทที่ไม่ได้รับการสนับสนุนอย่างสวยงามผ่านการจัดการข้อยกเว้น