2010-11-09 6 views
3

$ 7.3.3/14 (C++ 03)Разрешение перегрузки/Неоднозначность поиск имен (который один)

struct A { int x(); }; 
struct B : A { }; 
struct C : A { 
    using A::x; 
    int x(int); 
}; 
struct D : B, C { 
    using C::x; 
    int x(double); 
}; 
int f(D* d) { 
    return d->x(); // ambiguous: B::x or C::x 
} 

Комментарий в коде в 'F' указывает на то, что можно ожидать неоднозначность между «B :: x 'или' C :: x '.

Однако при компиляции с g ++ (ideone) или Comeau ошибки несколько отличаются. Эти ошибки вместо индикации неоднозначность в B :: х или C :: х указывают на тот факт, что А является неоднозначным база D

prog.cpp: In function ‘int f(D*)’: prog.cpp:16: error: ‘A’ is an ambiguous base of ‘D’

И

"ComeauTest.c", line 21: error: base class "A" is ambiguous return d->x(); // ambiguous: B::x or C::x

Переход по правилам поиска имен в $ 10.2 , Я чувствую, что комментарий в фрагменте кода не совсем правильный. Ошибка действительно в первую очередь связана с двусмысленностью базового класса «А», а не с чем-либо еще (например, двусмысленность в разрешении перегрузки). Есть предположения?

+1

Интересно, что Visual C++ 10.0 компилирует выше, выбирая подобъект A в B ... Я мог бы это понять, если он выбрал подобъект A в C. Кажется, что g ++ и Comeau сначала разрешают функцию-член как A :: x(), а затем обнаруживают, что d-> A :: x() неоднозначно. Но, что интересно, Visual C++ 10.0 компилирует даже это! –

+0

@Alf P. Steinbach: Да. Это было удивительно и для меня – Chubsdad

+0

Поскольку у меня нет компилятора C++ 03, я надеюсь, что этот вопрос будет терпеть ... Как насчет использования виртуального ключевого слова, как в struct D: virtual B, C или struct D: виртуальный C, виртуальный B? – JimR

ответ

2

Это вызвано поворотом на имя-поиске в C++ 03: Проверка для однозначного подобъекта была частью члена класса поиск имени в C++ 03. Поиск в C++ 03 найдет D :: X и C :: x и A :: x, где A :: x совпадает, но связан с двумя отдельными подобъектами типа A.

В C++ 0x , проверка для однозначного подобъекта теперь является частью соответствующих подразделов см DR #39: классом, где x непосредственно членом является неоднозначной базой - так пункт 5 вызовет ошибку компиляции, вместо пункта 10.

Обратите внимание, что в комментарии говорится о подобъектах A. Существует один подобъект A, который проходит по пути B и еще один подобъект A, который проходит по пути C. Вот почему в комментарии говорится: «B::x или C::x». Наличие нескольких подобъектов одного и того же типа класса можно определить, просто попытавшись преобразовать его в тип класса, игнорируя проблемы доступности: если преобразование неоднозначно, подобъект появляется несколько раз.

+0

Да. Я помню предыдущую дискуссию об этом. Моя точка зрения, однако, на этот раз, если комментарий в примере кода действительно подходит. По какой-то причине я чувствую, что «// неоднозначный: B :: x или C :: x» находится в контексте перегрузки, особенно когда в образце есть две перегрузки «x», видимые в примере – Chubsdad

+0

@Chubsdad комментарий не говорить о объявлениях в 'B' или' C', но о выборе подобъекта типа A. Если вы написали 'd-> B :: x()' или 'd-> C :: x() 'вы не получите никакой двусмысленности, потому что поиск начнется с' B' и 'C' соответственно. –

+0

В C++ 0x спецификация более понятна: три четко различимых шага: 1) Поиск объявлений (10.2) и разрешение перегрузки. Это найдет 'A :: x'. 2) Проверка того, является ли выражение объекта (однозначно) конвертируемым в класс именования '(в классе именования класса a-> c' есть тип' a', но в 'a-> b :: c', класс именования это 'b') - 11.2/6. И 3) Проверка того, является ли класс, в котором объявление является непосредственным членом, является однозначным базовым классом класса именования - 5.2.5/5. Ваш код нарушает '3)'. –

0

Clang ++ дает несколько комбинации ошибок, полученной г ++ и Коей

C:\Users\SUPER USER\Desktop>clang++ chubsdad.cpp 
chubsdad.cpp(12) : error: ambiguous conversion from derived class 'D' to base class 
     'A': 
    struct D -> struct B -> struct A 
    struct D -> struct C -> struct A 
    return d->x(); // ambiguous: B::x or C::x 
     ^
1 error generated. 
+0

О, хорошо. Благодарю. Я не уверен, хотя, если это ответит на мой вопрос об уместности и реальном намерении за комментарием в фрагменте кода – Chubsdad

+0

Я думаю, что 'неоднозначные: B :: x или C :: x' результаты от' 'A' - это двусмысленная база «D''. Так что комментарий в коде правильный ИМХО. –