Za pomocą poniższego kodu clang 3.0 podaje error: lookup of 'N' in member access expression is ambiguous
, natomiast clang 3.4 i gcc 4.8 akceptują kod bez błędu.Czy nazwa znaleziona w zależnej klasie bazowej powinna ukryć nazwę obszaru nazw w punkcie tworzenia instancji?
struct B
{
struct M
{
void f()
{
}
};
};
namespace N
{
struct M
{
void f()
{
}
};
}
template<typename>
struct A : N::M, B::M
{
typedef B N;
};
struct D : A<int>
{
A<int> m;
void f()
{
m.N::M::f(); // found class-name 'A<int>::N' (unambiguous)
}
};
template<typename T>
struct C : A<T>
{
A<T> m;
void f()
{
m.N::M::f(); // found namespace-name 'N' (ambiguous?)
}
};
template struct C<int>;
Po konsultacji standard nie jest dla mnie jasne, której zachowanie jest prawidłowe w odniesieniu do ekspresji w C<T>::f()
.
Ponieważ N
szuka się zarówno w zakresie klasy ekspresji obiektu n
(która zależy), w związku z ekspresją cały przyrostkiem (czyli zakres funkcji C<T>::f()
), konieczne jest, aby opóźnić wyszukiwanie do momentu wystąpienia.
W momencie wystąpienia wyszukiwanie będzie niejednoznaczne, jeśli znajdzie zarówno przestrzeń nazw N
, jak i typedef A<T>::N
. Deklaracja N
jest widoczna tylko wtedy, gdy nie jest ukryta przez deklarację A<T>::N
.
Pytanie brzmi, czy nazw N
należy uznać za ukryte przez typedef A<T>::N
gdy patrząc N
„w kontekście całego postfix ekspresji” i „w punkcie definicji szablonu”.
Cyt z projektu C++ roboczego w N3242 = 11-0012 (luty 2011): dostęp element
3.4.5 klasy [basic.lookup.classref]
Jeśli identyfikator ekspresja w sposób Użytkownik ma dostęp klasa wykwalifikowanym ID formy
class-name-or-namespace-name::...
the-or-nazw-nazwa klasy nazwa następnego operator
.
lub->
jest spojrzał w górę zarówno na w kontekście całego Postfix-expression oraz w zakresie klasy obiektu wyrażenia. Jeśli nazwa zostanie znaleziona tylko w zakresie zakresu klasy wyrażenia obiektowego, nazwa będzie odnosić się do nazwy klasy. Jeśli nazwa zostanie znaleziona tylko w kontekście całego wyrażeń postfiksowych, nazwa będzie odnosić się do nazwy klasy lub nazwy przestrzeni nazw. Jeśli nazwa znajduje się w obu kontekstach, nazwa-klasy-lub-nazwa-przestrzeni-nazwy powinna odnosić się do tej samej jednostki .14.6.4 rozdzielczości nazwa Zależnie [temp.dep.res]
w nim nazwy zależne nazwy z następujących źródłach uważa:
- oświadczenia, jakie są widoczne w punkcie definicji szablonu.
- Deklaracje z przestrzeni nazw powiązanych z typami argumentów funkcji zarówno z kontekstu tworzenia instancji (14.6.4.1), jak iz kontekstu definicji.
Jak można wymyślić taki kod? – jrok
@jrok: za dużo wolnego czasu –
tego rodzaju rzeczy pojawia się * cały czas * podczas pisania parsera C++;) – willj