Каковы правила поиска в пространстве имен для полных имен?

#c #namespaces #name-lookup

#c #пространства имен #поиск по имени

Вопрос:

Может кто-нибудь объяснить поведение, которое я вижу при поиске в пространстве имен для полных имен в следующем примере кода? См. Встроенные комментарии к проблеме.

 namespace ns1::hw
{

struct A1
{
   enum class E1
   {   
      E1_1,
      E1_2,
   };  
};

};

namespace ns1::ns2::hw
{

struct A2
{
   enum class E1
   {   
      E1_1,
      E1_2,
   };  
};

};

namespace ns1::ns2::ns3::hw
{

struct A3
{
   enum class E1
   {   
      E1_1,
      E1_2,
   };  
};

};

namespace ns1::ns2::ns3::ns4
{

struct A4
{
   int I1 { (int)hw::A3::E1::E1_1 }; // <--- this compiles OK
                                     // seems to search upwards in the parent namespace,
                                     // looking for the relative partially qualified
                                     // name.

   int I2 { (int)hw::A2::E1::E1_1 }; // <--- this doesn't
                                     // doesn't seem to apply the same search algorithm
                                     // beyond the immediate parent namespace.
};

};

int main()
{
   return 0;
} 
  

Ответ №1:

В вашем первом фрагменте:

    int I1 { (int)hw::A3::E1::E1_1 }; // <--- this compiles OK
                                     // seems to search upwards in the parent namespace,
                                     // looking for the relative partially qualified
                                     // name.
  

как вы, кажется, ожидаете, hw ищется в ns4 . Он не существует, поэтому его ищут в родительском пространстве ns3 имен . Он находит hw там, а затем находит вложенные имена A3 , затем E1 , а затем E1_1 , и поэтому поиск имени завершается успешно.

Во втором фрагменте:

    int I2 { (int)hw::A2::E1::E1_1 }; // <--- this doesn't
                                     // doesn't seem to apply the same search algorithm
                                     // beyond the immediate parent namespace.
  

на самом деле применяются те же правила. hw ищется в ns4 . Он не существует, поэтому его ищут в ns3 . Он найден там, но затем ему не удается найти вложенное имя A2 .

Теперь поиск имен будет идти только вверх по иерархии пространства имен. Он поднимется на столько уровней, сколько необходимо для поиска имени, но если он когда-либо найдет совпадение внутри уровня пространства имен, этот процесс остановится. Если позже он обнаружит отсутствующее вложенное имя, он не пойдет в обратном направлении и продолжит поиск вверх по иерархии пространства имен, вместо этого это просто серьезная ошибка.

В этом случае, если бы не hw было in ns3 , тогда поиск перешел бы к родительскому пространству ns2 имен, а затем к вложенным именам A2 , E1 , и E1_1 был бы найден успешно.

Комментарии:

1. Спасибо. Я ожидал, что это будет больше похоже, например, на то, как cpp ищет включаемые файлы. Он пытается найти относительный путь во всем пространстве поиска. Он не остановится только потому, что найдет начальную часть имени.

2. @Ziffusion Да, правила поиска имен отличаются. Я не уверен, есть ли для этого фундаментальная причина, возможно, из-за такого правила возникнут двусмысленности. По крайней мере, я думаю, что это было бы довольно болезненно для реализации.