2015-06-11 10 views
12

Рассмотрим следующий код:static_assert зависят от шаблона класса

template <unsigned int N> 
struct myclass 
{ 
    unsigned int f() {return N;} 
    unsigned int g() {static_assert(N > 0, ""); return N-1;} 
}; 

Вопрос: Есть ли у меня гарантия, что следующий код будет компилировать:

myclass<0> c; 
c.f(); 

Но следующий не будет:

myclass<0> c; 
c.f(); 
c.g(); 
+0

Конечно, первым не создает экземпляр «г» (кроме того, частный характер функций) –

+0

@ DieterLücking Изменен класс для структуры. – Vincent

+0

@ Vincent f() следует обнародовать, а также g() –

ответ

11

Да, у вас есть эта гарантия. Из [temp.inst]/11, курсив мой:

Реализация не должна неявно инстанцирует шаблон функции, переменной шаблон, шаблон члена, не-виртуальной функции члена, член класс или статический элемент данных шаблона класса , что не требует создания экземпляра.

Если вы не вызываете g(), он не требует создания экземпляра, и поэтому не должно быть никаких вопросов, требующих myclass<0>{}.f().

Это та же гарантия, что позволяет использовать std::vector и std::map с типами, которые не по умолчанию построимых до тех пор, пока вы не делать вещи, как вызов resize() и operator[] соответственно.

Followup как Jarod42 points out, что явно инстанцирование myclass<0> будет производить Assert, потому что, из [temp.explicit]/8:

Явного экземпляр, что имена шаблона класса специализация также является явной экземпляр такого же вида (декларация или определение) каждого из его членов (не включая членов, унаследованных от базовых классов и членов, которые являются шаблонами), которые ранее не были явно специализированы в переводе единица, содержащая явный экземпляр n, за исключением случаев, описанных ниже.

Исключения здесь не применяются.

+1

Обратите внимание, что явным образом создайте экземпляр 'myclass <0>' ('template struct myclass <0>;') будет выдавать assert. – Jarod42

+0

Pedantic: «у вас есть эта гарантия» по сравнению с обычным отказом от ответственности, что стандарту требуется только диагностическое сообщение, когда статическое утверждение срабатывает и не требует компиляции для отказа. –

+0

@Barry: у вас есть пример того, как я могу сделать компиляцию неудачной, используя resize() для вектора для типа, который не является конструктивным по умолчанию? – Vincent

-1

Если вы хотите отключить функцию во время компиляции, вы должны использовать enable_if вместо static_assert

template<unsigned int N> 
struct Foo { 
    unsigned int f() {} 
    enable_if_t<(N > 0), unsigned int> g() {} 
}; 

Foo<0> t{}; 
t.f(); /// this is okay and will compile 
// t.g() if I uncomment this line, it will not compile anymore. 
+0

Не обязательно. Использование enable_if выше некорректно для одной вещи, так как вы должны быть в шаблоном контексте для работы. Даже превращая это в шаблонную функцию-член, enable_if действительно для добавления/удаления чего-либо в набор кандидатов, а не для того, чтобы всегда требовать жесткую ошибку при попытке вызвать. – Nevin

+0

Это не будет скомпилировано, ваше разрешение, если оно не в контексте, в котором применяется SFINAE, так что это просто сложный сбой. – Barry

0

Использование специализации шаблона:

template <unsigned N> 
struct myclass 
{ 
    unsigned f() { return N; } 
    unsigned g() { return N-1; } 
}; 

template <> 
struct myclass <0> 
{ 
    unsigned f() { return 0; } 
}; 
+0

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

+0

@BenVoigt Правда, но я думаю, что на практике шаблоны классов, предназначенные для обеспечения ограничений, не содержат (и не должны) содержать многое другое. – KevinZ

 Смежные вопросы

  • Нет связанных вопросов^_^