2015-05-23 2 views
2
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)static_assert не удается проверить шаблонный указатель объекта

Каковы обходные пути? Поскольку я использую абстрактные шаблонные классы, это было бы кошмаром, если бы утверждение выполнялось только при создании экземпляра объекта без указателя. Я могу использовать завод, но это не совсем правильное решение.

+3

Это не совсем ответа на ваш вопрос, потому что это полезно иметь обходной путь, но * Если шаблон класса специализация не была явно инстанциирована явно специализирована, шаблон класса специализации неявно инстанцирована когда специализация ссылается в контексте , который требует полностью определенного типа объекта или когда полнота типа класса влияет на семантику программы. * – chris

+1

У вас может быть указатель на неполный тип, поэтому инстанцирование не запускается когда вы просто создаете указатель на этот тип. –

ответ

6

Вы несомненно видели эту цитату из §14.7.1/1:

Если шаблон класса специализация не была явно инстанцированной (14.7.2) или явно специализированной (14.7.3), класс шаблонная спецификация неявно создается , когда специализация ссылается в контексте, который требует полностью определенного типа объекта или когда полнота класса влияет на семантику программы.

Типы указателей не требуют их pointee быть полный тип (например, 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> [...] неявным экземпляр. - конец пример]

+0

Так есть обходной путь? Чтобы убедиться, что статическое утверждение разобрано? – crezefire

+0

@crezefire Да, убедитесь, что специализация создана. – Columbo