มีช่องว่างชื่ออะไรบ้างและมีกฎอะไรบ้าง


9

หมายเหตุ: คำถามนี้เป็นเรื่องเกี่ยวกับที่ไม่ได้name spacenamespace

มาตรฐาน C ++ มีการอ้างอิงบางอย่างname spaceแต่ฉันไม่เห็นคำจำกัดความของสิ่งนี้ มาตรฐานบอกว่าฉลากและมาโครอยู่ในพื้นที่ชื่อที่แตกต่างกัน การอ้างอิงอื่น ๆ ทั้งหมดที่name spaceอยู่ในส่วนความเข้ากันได้ของ C / C ++ เช่นนี้ ( ฉบับร่างปัจจุบัน ):

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

คำจำกัดความพื้นที่ชื่อใหม่นี้คืออะไร ฉันจะหาได้ในมาตรฐาน กฎที่แน่นอนคืออะไร? กฎดูเหมือนจะซับซ้อนกว่า "ประเภทการซ่อนประเภทที่ไม่ใช่" เช่นนี้ไม่ได้รวบรวม:

typedef int Foo; // Foo is a type
void Foo();      // not a type, but compile error, instead of hiding

แต่สิ่งนี้จะ:

struct Foo { }; // Foo is a type as well
void Foo();     // This hides the type Foo. "struct Foo" refers to the type

และนี่ไม่ได้รวบรวมอย่างใดอย่างหนึ่ง:

struct Foo { };   // Type
namespace Foo { } // Non-type, but compiler error instead of hiding

มุมมองที่ใช้งานได้คือเนมสเปซเป็นคลาสเดี่ยวที่มีสมาชิกแบบพับลิกทั้งหมด (คลาสย่อย) โปรดอย่าลงโทษฉัน :-)
peterh - Reinstate Monica

2
@ peterh-ReinstateMonica อ่านคำถาม (อีกครั้ง)
YSC

FWIW ลิงก์ของคุณเชื่อมโยงไปยังส่วนที่เกี่ยวข้อง: subclause ที่ได้รับผลกระทบ: [class.name] [ดูเพิ่มเติม [dcl.typedef]] คุณสามารถดูส่วนเหล่านี้สำหรับวิธีการทำงานของกฎ
NathanOliver

หนึ่งสำหรับป้ายชื่อ: มีอย่างน้อยสองช่องว่างชื่อและหนึ่งสำหรับแมโคร[stmt.label]/1 [cpp]/8
YSC

1
มันค่อนข้างน่าสนใจ (สำหรับฉัน) ว่าทั้งคำอธิบายและตัวอย่างแสดงสิ่งที่ตรงกันข้ามกับเหตุผลที่กล่าวถึง ชื่อประเภทซ่อนชื่อที่ไม่ใช่ประเภท เมื่อพิจารณาถึงสถานะของร่างฉันคาดว่าย่อหน้านั้นจะเปลี่ยนไป
molbdnilo

คำตอบ:


2

คำว่า space nameอาจเป็นที่ยอมรับในมาตรฐาน ISO C มากกว่า อ้างถึงISO C11 :

6.2.3 การเว้นวรรคของตัวระบุ

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

  • ชื่อฉลาก (disambiguated โดยไวยากรณ์ของการประกาศฉลากและการใช้งาน);
  • แท็กของโครงสร้างสหภาพและการแจกแจง (disambiguated โดย any32) ของคำหลัก struct, union หรือ enum)
  • สมาชิกของโครงสร้างหรือสหภาพ แต่ละโครงสร้างหรือสหภาพมีพื้นที่ชื่อที่แยกต่างหากสำหรับสมาชิก (disambiguated ตามประเภทของการแสดงออกที่ใช้ในการเข้าถึงสมาชิกผ่านทางผู้ประกอบการหรือ ->);
  • ตัวระบุอื่น ๆ ทั้งหมดที่เรียกว่าตัวระบุสามัญ (ประกาศในตัวประกาศธรรมดาหรือเป็นค่าคงที่การแจงนับ)

ใหม่นิยามพื้นที่ชื่อของ C ++ เป็น แต่ไม่ได้ในทางใด ๆที่ผ่านมาในเวลาและได้รับการอธิบายไว้ใน [diff.class] / 1 ในรูปแบบปัจจุบันนับตั้งแต่การเปิดตัวมาตรฐาน ISO c ++ มาตรฐานใน '98 มันเคยถูกกล่าวถึงในความยาวในบริบทที่แตกต่างจาก ISO C ตาม [diff.class] / 1 ซึ่งอ้างอิงโดย OP

Afaics เราต้องหันมาใช้ ISO C11 / 6.2.3 และรวมเข้ากับ [diff.class] / 1 ของมาตรฐาน ISO C ++ สำหรับคำอธิบายที่กระชับและสมบูรณ์ของคำจำกัดความของชื่อ(ใหม่) ของ C ++ซึ่งน้อยกว่าที่เราจะทำให้ ISO แย่ลง C ++ มาตรฐานสำหรับเช่น[basic.scope.hiding] , [class.name] / 2 , [stmt.label] / 1 , [cpp.replace] / 8และอื่น ๆ เพื่อดูวิธีการและตำแหน่ง

[class.name] / 2

การประกาศคลาสแนะนำชื่อคลาสลงในขอบเขตที่มีการประกาศและซ่อนคลาสตัวแปรฟังก์ชันหรือการประกาศอื่น ๆ ของชื่อนั้นในขอบเขตที่ล้อมรอบ [ ... ]

[stmt.label] / 1

[... ] ป้ายกำกับมีพื้นที่ชื่อของตนเองและไม่รบกวนตัวระบุอื่น ๆ [... ]

[cpp.replace] / 1

[... ] มีช่องว่างชื่อหนึ่งชื่อแมโคร [ ... ]


1

ใน C (6.2.3 ช่องว่างชื่อของตัวระบุ) ความคิดของช่องว่างชื่อมีการกำหนดวิธีการดังต่อไปนี้

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

- ชื่อฉลาก (disambiguated โดยไวยากรณ์ของการประกาศฉลากและการใช้งาน);

- แท็กของโครงสร้างสหภาพและการแจกแจง (disambiguated โดยการติดตามใด ๆ 32) ของโครงสร้างคำหลักสหภาพหรือ enum)

- สมาชิกของโครงสร้างหรือสหภาพ แต่ละโครงสร้างหรือสหภาพมีพื้นที่ชื่อที่แยกต่างหากสำหรับสมาชิก (disambiguated ตามประเภทของการแสดงออกที่ใช้ในการเข้าถึงสมาชิกผ่านทางผู้ประกอบการหรือ ->);

- ตัวระบุอื่น ๆ ทั้งหมดที่เรียกว่าตัวระบุสามัญ (ประกาศในตัวประกาศธรรมดาหรือค่าคงที่การแจงนับ)

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

struct s
{
    int s;
};

void s( void );

struct s s1;

ในโค้ดนี้ชื่อแท็กsของโครงสร้างไม่ขัดแย้งกับชื่อฟังก์ชันs เนื่องจากชื่อแท็กจะต้องระบุด้วยคำstructสำคัญ

ใน C ++ structคุณได้รับอนุญาตให้ชื่อแท็กโครงสร้างการใช้งานโดยไม่ต้องคำหลัก

ตัวอย่างเช่น

struct s
{
    int s;
};

s s;

เป็นรหัสที่ถูกต้อง ในการประกาศนี้

s s;

ชื่อของตัวระบุที่ประกาศsจะซ่อนชื่อโครงสร้าง ดังนั้นถ้าอย่างนั้นคุณจะเขียนตัวอย่าง

s s1;

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

struct s
{
    int s;
};

s s;

struct s s1;

นี่คือคำอธิบายในใบเสนอราคาต่อไปนี้จากมาตรฐาน C ++ 20 (6.3.1 ภูมิภาคและขอบเขตการประกาศ)

4 กำหนดชุดการประกาศในขอบเขตการประกาศเดียวซึ่งแต่ละอันจะระบุชื่อที่ไม่มีเงื่อนไขเหมือนกัน

(4.1) - พวกเขาทั้งหมดจะอ้างถึงเอนทิตีเดียวกันหรือทั้งหมดอ้างถึงฟังก์ชั่นและฟังก์ชั่นแม่แบบ; หรือ

(4.2) - การประกาศหนึ่งครั้งจะต้องประกาศชื่อคลาสหรือชื่อการแจงนับที่ไม่ใช่ชื่อ typedef และการประกาศอื่น ๆ ทั้งหมดจะอ้างถึงตัวแปรเดียวกันสมาชิกข้อมูลที่ไม่คงที่หรือตัวแจงนับหรือทั้งหมดที่อ้างถึงฟังก์ชันและฟังก์ชันเทมเพลต ; ในกรณีนี้ชื่อคลาสหรือชื่อการแจงนับจะถูกซ่อน (6.3.10) [ หมายเหตุ: ชื่อเนมสเปซหรือชื่อเทมเพลตคลาสต้องไม่ซ้ำกันในภูมิภาคที่ประกาศ (10.3.2 ข้อ 17) - บันทึกท้าย ]

ดังที่คุณเห็นจากเครื่องหมายคำพูดชื่อเนมสเปซจะต้องไม่ซ้ำกันในภูมิภาคที่ประกาศ ดังนั้นการประกาศเหล่านี้

struct Foo { };
namespace Foo { } 

ไม่ถูกต้อง

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