ความหมายแบบอินไลน์ในโมดูลอินเตอร์เฟส


24

พิจารณาไฟล์ส่วนหัว:

class T
{
private:
  int const ID;

public:
  explicit T(int const ID_) noexcept : ID(ID_) {}

  int GetID() const noexcept { return ID; }
};

หรืออีกทางหนึ่ง:

class T
{
private:
  int const ID;

public:
  explicit T(int const ID_) noexcept;

  int GetID() const noexcept;
};

inline T::T(int const ID_) noexcept : ID(ID_) {}

inline int T::GetID() const noexcept { return ID; }

ในโลกก่อนโมดูลส่วนหัวเหล่านี้อาจรวมอยู่ใน textually ใน TU หลายรายการโดยไม่มีการละเมิด ODR นอกจากนี้เนื่องจากการทำงานของสมาชิกที่เกี่ยวข้องกับการมีขนาดค่อนข้างเล็กคอมไพเลอร์น่าจะ "อินไลน์" (ฟังก์ชั่นหลีกเลี่ยงการโทรเมื่อใช้) ฟังก์ชั่นเหล่านั้นหรือแม้กระทั่งการเพิ่มประสิทธิภาพออกไปบางส่วนกรณีของTทั้งหมด

ในรายงานล่าสุดเกี่ยวกับการประชุมที่ C ++ 20 เสร็จสิ้นฉันสามารถอ่านข้อความต่อไปนี้:

เราชี้แจงความหมายของinlineในอินเทอร์เฟซโมดูล: เจตนาคือเนื้อความของฟังก์ชันที่ไม่ได้ประกาศไว้อย่างชัดเจนinlineไม่ได้เป็นส่วนหนึ่งของ ABI ของโมดูลแม้ว่าฟังก์ชันของฟังก์ชันเหล่านั้นจะปรากฏในส่วนต่อประสานโมดูล เพื่อที่จะให้ผู้เขียนโมดูลการควบคุมที่มากกว่า ABI inlineของพวกเขาฟังก์ชั่นสมาชิกที่กำหนดไว้ในร่างกายในระดับอินเตอร์เฟซโมดูลนี้ไม่มีอีกต่อไปโดยปริยาย

ฉันไม่แน่ใจว่าฉันไม่ผิด นั่นหมายความว่าในโลกของโมดูลเพื่อให้คอมไพเลอร์สามารถเพิ่มประสิทธิภาพการเรียกใช้ฟังก์ชันเราต้องใส่คำอธิบายประกอบราวกับinlineว่ามันถูกกำหนดไว้ในคลาส?

ถ้าเป็นเช่นนั้นส่วนต่อไปนี้ของโมดูลจะเทียบเท่ากับส่วนหัวด้านบนหรือไม่

export module M;

export
class T
{
private:
  int const ID;

public:
  inline explicit T(int const ID_) noexcept : ID(ID_) {}

  inline int GetID() const noexcept { return ID; }
};

แม้ว่าฉันจะยังไม่มีคอมไพเลอร์ที่สนับสนุนโมดูล แต่ฉันต้องการเริ่มใช้inlineเช่นนั้นเมื่อเหมาะสมเพื่อลดการปรับโครงสร้างในอนาคต

คำตอบ:


11

นั่นหมายความว่าในโลกของโมดูลเพื่อให้คอมไพเลอร์สามารถเพิ่มประสิทธิภาพการเรียกใช้ฟังก์ชันเราต้องใส่คำอธิบายประกอบราวกับinlineว่ามันถูกกำหนดไว้ในคลาส?

ในระดับหนึ่ง

Inlining เป็นการเพิ่มประสิทธิภาพแบบ "ราวกับว่า" และการอินไลน์สามารถเกิดขึ้นได้ระหว่างหน่วยการแปลหากคอมไพเลอร์ฉลาดพอ

ดังที่กล่าวไว้การใช้งานง่ายที่สุดเมื่อทำงานภายในหน่วยการแปลเดียว ดังนั้นเพื่อส่งเสริมการ inlining ง่ายinlineฟังก์ชั่น -declared จะต้องมีความหมายของมันให้ไว้ในหน่วยการแปลใด ๆ ที่มันถูกนำมาใช้ นี่ไม่ได้หมายความว่าคอมไพเลอร์จะอินไลน์มันอย่างแน่นอน (หรือไม่แน่นอนไม่ได้อยู่ในinlineฟังก์ชั่นที่ไม่มีคุณสมบัติ) แต่มันทำให้สิ่งต่าง ๆ ง่ายขึ้นมากในกระบวนการอินไลน์เนื่องจากกระบวนการอินไลน์เกิดขึ้นภายใน TU มากกว่าระหว่างพวกเขา

คำจำกัดความของสมาชิกคลาสที่กำหนดไว้ภายในคลาสในโลกก่อนโมดูลจะถูกประกาศinlineโดยปริยาย ทำไม? เพราะคำจำกัดความอยู่ในคลาส ในโลกก่อนโมดูลคำจำกัดความของชั้นเรียนที่ใช้ร่วมกันในหมู่มหาวิทยาลัยธรรมศาสตร์มีการแบ่งปันโดยการรวมข้อความ สมาชิกที่กำหนดไว้ในชั้นเรียนจะถูกกำหนดไว้ในส่วนหัวที่ใช้ร่วมกันในหมู่ TU เหล่านั้น ดังนั้นถ้าหลาย TU ใช้คลาสเดียวกันนั้น TU หลาย ๆ ตัวนั้นกำลังทำอยู่โดยการรวมคลาส definition และนิยามของสมาชิกที่ประกาศไว้ในส่วนหัว

นั่นคือคุณรวมถึงคำจำกัดความแล้วทำไมไม่ทำอย่างนั้นinlineล่ะ?

แน่นอนนี่หมายความว่าคำจำกัดความของฟังก์ชั่นตอนนี้เป็นส่วนหนึ่งของข้อความของชั้นเรียน หากคุณเปลี่ยนนิยามของสมาชิกที่ประกาศในส่วนหัวสิ่งนี้จะบังคับให้คอมไพล์ใหม่ของทุกไฟล์ที่มีส่วนหัวนั้นซ้ำ แม้ว่าอินเทอร์เฟซของคลาสจะไม่เปลี่ยนแปลง แต่คุณยังต้องทำการคอมไพล์ใหม่ ดังนั้นการทำฟังก์ชั่นดังกล่าวโดยปริยายinlineจะไม่เปลี่ยนแปลงสิ่งนี้ดังนั้นคุณอาจทำเช่นนั้นได้

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

แต่นี่คือสิ่งที่: นี่คือสิ่งประดิษฐ์ของการใช้การรวมข้อความเป็นวิธีการส่งมอบชั้นเรียนไปยังสถานที่หลายแห่ง

ในโลกโมดูลาร์คุณอาจต้องการกำหนดฟังก์ชั่นสมาชิกแต่ละตัวภายในคลาสเองดังที่เราเห็นในภาษาอื่นเช่น Java, C #, Python และอื่น ๆ การทำเช่นนี้ช่วยให้โค้ดโลคัลสมเหตุสมผลและป้องกันไม่ให้พิมพ์ลายเซ็นฟังก์ชันซ้ำอีกครั้งดังนั้นจึงตอบสนองความต้องการของ DRY

inlineแต่ถ้าสมาชิกทุกคนได้กำหนดไว้ในการกำหนดระดับแล้วภายใต้กฎระเบียบเก่าของสมาชิกทุกคนผู้ที่จะเป็น และเพื่อให้โมดูลสามารถใช้ฟังก์ชันได้inlineสิ่งประดิษฐ์โมดูลไบนารีจะต้องมีคำจำกัดความของฟังก์ชันเหล่านั้น ซึ่งหมายความว่าเมื่อใดก็ตามที่คุณเปลี่ยนรหัสแม้แต่บรรทัดเดียวในการกำหนดฟังก์ชั่นโมดูลจะต้องถูกสร้างขึ้นพร้อมกับทุกโมดูลขึ้นอยู่กับมันซ้ำ ๆ

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


8

สิ่งนี้มาจากP1779เพิ่งนำไปใช้ในกรุงปรากเมื่อไม่กี่วันที่ผ่านมา จากข้อเสนอ:

บทความนี้เสนอให้นำสถานะอินไลน์โดยนัยออกจากฟังก์ชั่นที่กำหนดไว้ในคำจำกัดความของคลาสที่แนบกับโมดูล (ชื่อ) สิ่งนี้อนุญาตให้คลาสได้รับประโยชน์จากการหลีกเลี่ยงการประกาศซ้ำซ้อนรักษาความยืดหยุ่นที่เสนอให้แก่ผู้เขียนโมดูลในการประกาศฟังก์ชันที่มีหรือไม่มีอินไลน์ นอกจากนี้ยังช่วยให้เพื่อนที่ถูกฉีดของเทมเพลตคลาส (ซึ่งไม่สามารถกำหนดได้โดยทั่วไปนอกนิยามคลาส) จะไม่อินไลน์เลย นอกจากนี้ยังช่วยแก้ NB คิดเห็นUS90

กระดาษ (เหนือสิ่งอื่นใด) ออกประโยค:

ฟังก์ชั่นที่กำหนดไว้ในคำจำกัดความของชั้นเรียนเป็นฟังก์ชั่นแบบอินไลน์

และเพิ่มประโยค:

ในโมดูลส่วนกลางฟังก์ชั่นที่กำหนดไว้ในคำจำกัดความของคลาสนั้นอินไลน์โดยนัย ([class.mfct], [class.friend])


ตัวอย่างของคุณexport module Mจะเทียบเท่ากับโมดูลของโปรแกรมเริ่มต้น โปรดทราบว่าคอมไพเลอร์ได้ทำฟังก์ชั่นอินไลน์ที่ไม่ได้ใส่คำอธิบายประกอบinlineเป็นเพียงว่าพวกเขาใช้การปรากฏตัวของinlineคำหลักในการวิเคราะห์พฤติกรรมของพวกเขา


ดังนั้นฟังก์ชั่นในโมดูลที่ไม่มีinlineคีย์เวิร์ดจะไม่มีการคอมไพล์โดย inline ใช่ไหม?
metalfox

1
@ metalfox ไม่ฉันไม่เชื่อว่าถูกต้อง
Barry

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