C ++ 11 static_assert и создание шаблона
В C ++ 11, если операция static_assert в шаблоне зависит от того, был ли этот экземпляр создан или нет? Например, со следующим кодом
template void sa() { static_assert(0,"Hello."); } int main(int argc, char *argv[]) { return 0; }
GCC 4.5.0 не выполнит это утверждение и произведет «Привет». сообщение. С другой стороны, компилятор Digital Mars 8.42n не дает сообщений.
- shared_ptr относится к weak_ptr как unique_ptr для ... чего?
- В C ++ какие категории (lvalue, rvalue, xvalue и т. Д.) Могут выражать выражения, которые производят временные classы типа classа?
- Как удалить с карты при ее повторении?
- c ++ доступ к статическим членам с использованием нулевого указателя
- Как я могу расширить кортеж в аргументы функции вариационной матрицы?
- О том, как распознать ссылку Rvalue или Lvalue и правило if-it-have-a-name
- Теперь, когда у нас есть std :: array, какие применения остаются для массивов в стиле C?
- В C ++ существует ли еще плохая практика вернуть вектор из функции?
- неclassовые значения всегда имеют cv-неквалифицированные типы
- Когда дополнительные скобки имеют эффект, отличные от приоритета оператора?
- перегрузка constexpr
- Как проверить поддержку C ++ 11?
- Когда использовать std :: forward для пересылки аргументов?
GCC правильный, и другой компилятор тоже прав. См. 14.6p8 в спецификации
Если для определения шаблона не может быть создана достоверная специализация, и этот шаблон не создается, определение шаблона плохо сформировано, не требуется диагностика.
Поэтому компилятор может отклонить следующие
template void f() { static_assert(0, "may trigger immediately!"); static_assert(sizeof(T) == 0, "may trigger immediately!"); }
Если вы хотите пойти в безопасное место, вам необходимо его организовать, чтобы компилятор не смог узнать, пока не будет установлено, будет ли логическое выражение истинным или ложным. Например, получите значение getvalue
, причем getvalue
является шаблоном classа (можно было бы его специализировать, поэтому компилятор не может знать булевское значение уже).
Я считаю, что компилятор в своих правах имеет право расширять любые статические утверждения, которые не зависят от параметров шаблона без необходимости создания экземпляра, но я не считаю, что это необходимо. Помните также, что различные проекты стандартов могут иметь разные правила о том, когда это может произойти.
Проект C ++ 0x ( N3242 ) говорит в 14.6p8:
«Если для определения шаблона не может быть создана действительная специализация, и этот шаблон не создается, определение шаблона плохо сформировано, а диагностика не требуется».
Эти же слова появляются в стандарте C ++ 03.
В случае примера из вопроса, для этого шаблона не может быть выполнено действительное создание экземпляра, поэтому применяется цитированная формулировка.
Поскольку диагностика не требуется, компилятор может скомпилировать программу, если шаблон не создан. Конечно, если он создается, программа плохо сформирована, и требуется диагностика.
Я использовал вспомогательную функцию, чтобы сделать ложную зависимость от параметра шаблона:
template bool dependentFalse() { return false; } template Foo foo() { static_assert(dependentFalse(), "this template shouldn't be instantiated"); }
Это раздел 14.6.2
в стандарте C ++.
Ваш static_assert
связан с поддержкой привязки независящих имен при первоначальном анализе шаблона . Компилятор Digital Mars Compiler в настоящее время не поддерживает привязные независимые имена. GCC 4.5.0 поддерживает привязку не зависящих имен.
Если ваше выражение не зависит от параметров шаблона, тогда такое выражение известно при первоначальном анализе шаблона. Компилятор должен показать сообщение об ошибке. GCC 4.5.0 делает это.
Замените свой 0
в static_assert
на I*I < 0
, для примера, и вы получите зависимое имя. Сообщение об ошибке появится только для случая незакрепленного шаблона.
Эта программа генерирует ошибку:
template void sa() { static_assert(0,"Hello."); } template <> void sa<0>() { } int main(int argc, char *argv[]) { return 0; }
Эта программа не выполняет:
template void sa() { static_assert(I != 0,"Hello."); } template <> void sa<0>() { } int main(int argc, char *argv[]) { return 0; }
Это не имеет никакого смысла для этого. Поэтому я пришел к выводу, что g ++ 4.5 должен быть ошибкой, если он запускает static_assert
в незакрепленном шаблоне.
И еще более тревожная, следующая программа печатает I == 1
.
#include using ::std::cout; template void sa() { cout << "I == " << I << '\n'; static_assert(I != 0,"Hello."); } template <> void sa<0>() { cout << "I == " << 0 << '\n'; } int main(int argc, char *argv[]) { sa<1>(); return 0; }
Это указывает на серьезную ошибку в том, как gcc обрабатывает static_assert
.
Редактировать : О, хорошо. В моей программе есть ошибка. Он должен читать I == 0
, а не I != 0
, и если это было изменено, оно не скомпилируется так, как должно.