У меня есть класс шаблона NB::B
, производный от класса шаблона, отличного от -, NA::A
в пространстве имен. act
— это функция шаблона, вызывающая функцию add_ref
для экземпляра своего аргумента шаблона. В частности, act
хочет найти add_ref
, определенный в пространстве имен базы NB::B
, используя ADL. Полный пример следующий:
template
void act() {
T* p = 0;
add_ref(p); // the failing line
}
namespace NA
{
struct A { };
// I want ADL to find this:
void add_ref(A* p) {
}
}
namespace NB
{
// template class with non-template base
template
struct B: NA::A { };
typedef B Bi;
// using NA::add_ref; // fixes the problem
}
int main()
{
act();
}
Это нормально компилируется вgcc
(4.7.0 ). И в Comeau
онлайн. Однакоclang
(3.1 )не работает:
a.cpp:4:3: error: use of undeclared identifier 'add_ref'
В то же время стандарт гласит:
3.4.2/2 …
— If T is a template-id, its associated namespaces and classes are the namespace in which the template is defined; for member templates, the member template’s class; the namespaces and classes associated with the types of the template arguments provided for template type parameters (excluding template template parameters); the namespaces in which any template template arguments are defined; and the classes in which any member templates used as template template arguments are defined.
Удивительно, но базы шаблонов не указаны как пути к связанным пространствам имен. Таким образом, поведение clang
кажется правильным. А Comeau
и gcc
принимают неверную программу.
В то же время 3.4.2/3
утверждает, что using
в пространствах имен аргументов не действуют :
When considering an associated namespace, the lookup is the same as the lookup performed when the associated namespace is used as a qualifier (3.4.3.2) except that:
— Any using-directives in the associated namespace are ignored.
. Но когда я раскомментирую строку using NA::add_ref
clang
, я с удовольствием скомпилирую тест.
Чтобы представить мой пример в практической перспективе, вы можете подумать, что act
был методом boost::intrusive_ptr
, add_ref(A*)
был intrusive_ptr_add_ref(CBase*)
, а B
был неким шаблоном, производным от базы CBase
.
В связи с этим у меня есть несколько вопросов:
Прав ли я, что clang
правильно отвергает мою тестовую программу, а gcc
и Comeau
не соответствуют стандарту?
Есть ли причина, по которой стандарт определяет такое непрактичное поведение (, как запрет на использование баз классов шаблонов в качестве связанных пространств имен )?
Является ли clang
неправильным принятие моей тестовой программы с директивой using NA::add_ref
на основании 3.4.2/3
?
Должен ли я сообщить об ошибке?:)
P.S. Я прочитал clang FAQ по языковой совместимости и не нашел там ответа.