Создает ли неявное создание экземпляра шаблона функции «используется как параметр шаблона, не являющийся типом»?
Я хочу написать шаблон класса
M
который принимает неполный тип в качестве параметра шаблона. Но я тоже хочу
C
имеет некоторые черты, когда он в конечном итоге будет определен.
Гарантирован ли этот код
- для компиляции, если определено (FLAG),
- и не выполнить компиляцию, если! определено (FLAG)?
template <auto> struct Dummy {};
template <typename C>
void check()
{
static_assert(std::is_trivial_v<C>);
}
template <typename C>
struct M : Dummy<&check<C>>
{
//static_assert(std::is_trivial_v<C>);//error: incomplete type
C * p;
};
struct Test;
M<Test> m;
int main()
{
return 0;
}
#if defined(FLAG)
struct Test {};
#else
struct Test { std::string non_trivial_member; };
#endif
1 ответ
Точка создания [временная точка] (17.7.4.1/8)
Специализация для шаблона функции, шаблона функции-члена или функции-члена или статического члена данных шаблона класса может иметь несколько точек создания экземпляров в единице перевода, а в дополнение к точкам создания экземпляров, описанным выше, для любых таких специализации, которая имеет точку создания в пределах единицы перевода, конец единицы трансляции также считается точкой создания экземпляра. Специализация для шаблона класса имеет не более одной точки создания экземпляра в единице перевода. Специализация для любого шаблона может иметь точки реализации в нескольких единицах перевода. Если две разные точки реализации придают специализации шаблона разные значения в соответствии с правилом одного определения (6.2), программа плохо сформирована, диагностика не требуется.
Во-первых, обратите внимание, что основной шаблон - это специализация в стандартной речи.
Во-вторых, в вашей программе есть две точки реализации; однажды в
M<Test> m;
и один раз в конце единицы перевода.
Значение at
M<Test> m
отличается от значения в конце единицы перевода. В одном месте,
Test
неполный, с другой - полный. Тело
check<Test>
определенно имеет другое значение.
Значит, ваша программа плохо сформирована, диагностика не требуется. В вашем случае плохо сформированная программа делает то, что вы хотите, но она может (по стандарту) скомпилировать что угодно или вообще не скомпилировать.
Я подозреваю, что причина этого правила заключается в том, чтобы дать компилятору свободу создавать экземпляр либо немедленно, либо отложить его на потом. Вам не разрешается полагаться на то, какое из двух мест фактически создает экземпляр тела
check
.