Разрешаване на претоварване: Как това не е двусмислено?

Да предположим, че имаме този код, копиран от отделен въпрос:

namespace x 
{
    void f()
    {
    }

    class C 
    {
        void f() 
        {
            using x::f;
            f();         // <==
        }
    };
}

Името f на посочения ред недвусмислено се отнася до x::f (поне според gcc и clang). Защо x::f се предпочита пред x::C::f в този случай? Не трябва ли да е двусмислено, тъй като се виждат и двете имена?


person Barry    schedule 05.12.2014    source източник


Отговори (3)


Тъй като декларацията using въвежда x::f в обхвата на f, който е по-тесен от този на C. Неквалифицираното търсене разглежда обхвата на локалния блок, намира съвпадение и спира, преди да вземе предвид по-широкия обхват на класа. Няма зависимо от аргумент търсене, тъй като няма функционални аргументи, така че не се разглеждат допълнителни обхвати.

person Mike Seymour    schedule 05.12.2014

Отговорът на @MikeSeymour е на място; ето съответните стандартни цитати (C++11, акцентът е мой):

13.3.1.1.1/3:

При неквалифицирани извиквания на функции името не е квалифицирано от оператор -> или . и има по-общата форма на първичен израз. Името се търси в контекста на извикването на функция, следвайки нормалния правила за търсене на имена при извиквания на функции (3.4). Функционалните декларации, открити от това търсене, съставляват набора от кандидат функции. Поради правилата за търсене на име, наборът от функции-кандидати се състои (1) изцяло от функции, които не са членове, или (2) изцяло от функции-членове от някакъв клас T. ...

3.4.1/1:

Във всички случаи, изброени в 3.4.1, обхватите се търсят за декларация в реда, посочен във всяка от съответните категории; търсенето на име приключва веднага щом бъде намерена декларация за името. Ако не бъде намерена декларация, програмата е неправилно оформена.

3.4.1/8

Име, използвано в дефиницията на функция член (9.3) от клас X след declarator-id на функцията ... трябва да бъде декларирано по един от следните начини:

  • преди използването му в блока, в който се използва, или в ограждащ блок (6.3), или
  • трябва да бъде член на клас X или да бъде член на базов клас X (10.2), или
  • ...

От 3.4.1/8 виждаме, че декларация за името f (като декларацията using x::f;) в блока, в който се използва, е посочена преди f като член на клас C. Съгласно 3.4.1/1 се избира по-ранният, така че цялото търсене се разрешава до x::f, въведено от декларацията using.

person Angew is no longer proud of SO    schedule 05.12.2014

Мисля, че тези цитати от стандарта C++ ще бъдат уместни:

От стандарта C++ (7.3.3 Декларацията за използване)

13 Тъй като декларацията за използване е декларация, ограниченията за декларации с едно и също име в същия декларативен регион (3.3) се прилагат и за декларациите за използване.

И (3.3.7 Обхват на класа)

4) Име, декларирано в членна функция, скрива декларация със същото име, чийто обхват се простира до или след края на класа на членската функция.

person Vlad from Moscow    schedule 05.12.2014