template <size_t N>
class Foo
{
static_assert(N > 0, "WRONG");
//void Something() = 0; //my original implementation
};
int main() {
Foo<0> *p2 = nullptr; //no error
Foo<0> p; //gives an error
return 0;
}
Я проверил обе строки отдельно. static_assert не вызывается при инициализации p2, но вызывается и действительно завершается с ошибкой на p. Это предназначено? (Я пробовал это на gcc, clang и vc)
Каковы обходные пути? Поскольку я использую абстрактные шаблонные классы, было бы кошмаром, если утверждение выполняется только тогда, когда создается экземпляр объекта без указателя. Я могу использовать фабрику, но это не совсем правильное решение.
Вы наверняка видели эту цитату из §14.7.1 / 1:
Если специализация шаблона класса не была явно
созданный (14.7.2) или явно специализированный (14.7.3) класс
специализация шаблона неявно создается когда
На специализацию ссылаются в контексте, который требует
полностью определенный тип объекта или когда полнота класса
Тип влияет на семантику программы.
Типы указателя не требуют, чтобы их указатель был полным типом (например, void*
является примером этого). Таким образом, первая строка не будет создавать экземпляр специализации, а вторая нужна, следовательно, утверждение относится только к этой.
Это также рассматривается в примере на три абзаца ниже:
[ пример:template<class T> struct Z { void f(); void g(); }; void h() { Z<int> a; // instantiation of class Z<int> required Z<double>* q; // instantiation of class Z<double> not required //[…] }
Ничто в этом примере не требует класса
Z<double>
[…] Быть неявно созданным. — конец примера ]