Создает ли неявное создание экземпляра шаблона функции «используется как параметр шаблона, не являющийся типом»?

Я хочу написать шаблон класса 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 ответ

От n4713,

Точка создания [временная точка] (17.7.4.1/8)

Специализация для шаблона функции, шаблона функции-члена или функции-члена или статического члена данных шаблона класса может иметь несколько точек создания экземпляров в единице перевода, а в дополнение к точкам создания экземпляров, описанным выше, для любых таких специализации, которая имеет точку создания в пределах единицы перевода, конец единицы трансляции также считается точкой создания экземпляра. Специализация для шаблона класса имеет не более одной точки создания экземпляра в единице перевода. Специализация для любого шаблона может иметь точки реализации в нескольких единицах перевода. Если две разные точки реализации придают специализации шаблона разные значения в соответствии с правилом одного определения (6.2), программа плохо сформирована, диагностика не требуется.

Во-первых, обратите внимание, что основной шаблон - это специализация в стандартной речи.

Во-вторых, в вашей программе есть две точки реализации; однажды в

      M<Test> m;

и один раз в конце единицы перевода.

Значение at M<Test> mотличается от значения в конце единицы перевода. В одном месте, Testнеполный, с другой - полный. Тело check<Test> определенно имеет другое значение.

Значит, ваша программа плохо сформирована, диагностика не требуется. В вашем случае плохо сформированная программа делает то, что вы хотите, но она может (по стандарту) скомпилировать что угодно или вообще не скомпилировать.

Я подозреваю, что причина этого правила заключается в том, чтобы дать компилятору свободу создавать экземпляр либо немедленно, либо отложить его на потом. Вам не разрешается полагаться на то, какое из двух мест фактически создает экземпляр тела check.