Sizeof класса шаблона
template<int N>
struct S
{
void foo()
{
sizeof( S ); // (*)
sizeof( S<N> );
}
};
int main()
{
S<5> s;
s.foo();
return 0;
}
Этот код компилируется отлично (VS2010), но я сомневаюсь в строке (*)
. S
не является полным типом, в отличие от S<N>
, на мой взгляд, тогда как компилятор знает свой размер? Что говорит стандарт о такой ситуации, правильно ли он сформирован правильно sizeof
?
Ответы
Ответ 1
Имя S
внутри определения struct S
относится к имени введенного класса S
, которое согласно 14.6.1/2 (С++ 03) не требует явного списка аргументов
В рамках специализации шаблона класса или частичного специализации, когда имя введенного класса не сопровождаемый символом <, он эквивалентен имени введенного класса а затем шаблонные аргументы специализация шаблона класса или частичная специализация, заключенная в < > .
Обратите внимание, что если вы намеренно вынуждаете компилятор использовать "оригинальное" имя шаблона (вместо введенного имени класса) с помощью оператора разрешения области, список параметров станет обязательным
template<int N>
struct S
{
void foo()
{
sizeof( ::S ); // <- ERROR
sizeof( ::S<N> ); // <- OK
}
};
Ответ 2
С++ неявно вставляет using S = S<N>;
в тело класса, поэтому оба утверждения эквивалентны.
template<int N>
struct S {
static_assert(std::is_same<S, S<N>>(), "");
};
Это была бы ошибка, если бы вы сделали sizeof(S)
вне определения S
.
Ответ 3
В шаблоне имя шаблона также является введенным именем класса и относится к типу класса S<N>
, а не к шаблону; и внутри функции члена класса тип класса завершен, даже если функция определена внутри класса. Таким образом, оба действительны и эквивалентны друг другу.
Ответ 4
Функции-члены шаблонов классов не создаются до их вызова. К этому времени класс уже будет создан, и компилятор получит всю необходимую ему информацию для расчета его размера.