Подтвердить что ты не робот

Переадресация объявления класса, используемого в функции шаблона, не компилируется clang++

Есть этот код:

class A;

template <class T>
void fun() {
   A a;
}

class A { 
public: 
   A() {  } 
};

int main() { 
   fun<int>(); 
   return 0;
}

g++ 4.5 и g++ 4.7 компилирует это без ошибок. Но clang++ 3.2 (trunk) дает эту ошибку:

main.cpp:5:6: error: variable has incomplete type 'A'
   A a;
     ^
main.cpp:1:7: note: forward declaration of 'A'
class A;
      ^

Какой компилятор прав в соответствии со стандартом С++?

4b9b3361

Ответ 1

Какой компилятор прав в соответствии со стандартом С++?

Оба правильные. Это плохо сформированная программа. Акцент мой:

N3290 14,6¶9
Если тип, используемый в не зависящем от имени имени, является неполным в точке, где шаблон определен, но завершен в момент, когда выполняется создание экземпляра, и если полнота этого типа влияет на то, формируется или влияет на семантику программы, программа плохо сформирована; диагностика не требуется.

Что clang++ и другие компиляторы действительно выпускают диагностику, здесь есть хорошая возможность добавить, но диагноз не является обязательным. Этот пункт "программа плохо сформирована, не требуется никакой диагностики" дает разработчику свободное свободное от компилятора делать что-либо в таких обстоятельствах и по-прежнему быть совместимым.

Ответ 2

Клэнг, насколько мне известно, верен. В вашей функции весело, вы не знаете размер A, и, поскольку вы выделяете A, вам нужно знать его размер. На мой взгляд, gcc - это способ простить здесь.

Ответ 3

clang++ использует правильное поведение, это описано в разделе 4.6/9 стандарта (n1905).


Templates 14.6/9 Name resolution

Если имя не зависит от параметра шаблона (как определено в 14.6.2) объявление (или набор деклараций) для этого имени должно быть в области действия в точке, где имя отображается в шаблоне определение; имя связано с объявлением (или декларациями) найденные в этот момент, и это обязательство не зависит от объявлений которые видны в момент создания экземпляра.


Сделать вещи проще; если имя не зависит от параметра шаблона, оно должно быть в области определения определения; поэтому перед определением template<typename T> void fun () вам нужно определить A.

Ответ 4

Компилятор Comeau тоже не нравится:

"ComeauTest.c", line 5: error: incomplete type is not allowed
     A a;
       ^

Однако мои попытки найти главу и стих в стандарте С++ оказались бесплодными. Кажется, он скрыт между линиями и взаимодействиями "точки инстанцирования", "разрешения имен". Пункты 14.6/8 и 14.6/9 стандарта 2003 года кажутся актуальными.