статический assert зависит от параметра шаблона не-типа (различное поведение на gcc и clang)
template <int answer> struct Hitchhiker {
static_assert(sizeof(answer) != sizeof(answer), "Invalid answer");
};
template <> struct Hitchhiker<42> {};
при попытке отключить общий экземпляр шаблона с static_assert
я обнаружил, что приведенный выше код в clang
генерирует ошибку assert, даже если шаблон не создан, в то время как gcc
генерирует ошибку assert только при создании экземпляра Hitchhiker
с параметром, кроме 42
.
возясь, я обнаружил, что это утверждение:
template <int answer> struct Hitchhiker {
static_assert(sizeof(int[answer]) != sizeof(int[answer]), "Invalid answer");
};
template <> struct Hitchhiker<42> {};
ведет себя одинаково на обоих компиляторах: assert срабатывает только тогда, когда общий шаблон создать экземпляр.
что говорит стандарт, какой компилятор прав?
g++ 4.9.2
clang++ 3.50
2 ответов
цитаты, найденные @TartainLlama
если гипотетический экземпляр шаблона сразу после его определения будет плохо сформирован из-за конструкции, которая не зависит от параметра шаблона, программа плохо сформирована; диагностика не требуется.
N4296 [temp.res] / 8
это применяется сразу после того, как основной шаблон определен (тот, с static_assert
в нем). Так что позже специализация (для 42
) нельзя рассматривать, так как он еще не существует.
следующий вопрос: если static_assert( sizeof(answer) != sizeof(answer),
зависит on answer
. Семантически это не так, синтаксически это так, и стандартно:
внутри шаблона, некоторые конструкции имеют семантику, которая может отличаться от одного экземпляра к другому. Такая конструкция зависит параметры шаблона.
N4296 [температура.dep] / 1
конструкция sizeof(answer) != sizeof(answer)
ничем не отличается от одного экземпляра к другому. Так что такая конструкция не зависит параметры шаблона. Что означает все static_assert
не зависит от параметра шаблона.
таким образом, ваша программа плохо сформирована, диагностика не требуется. Выдача произвольной диагностики (например,static_assert
failing) является допустимым поведением компилятора. Отсутствует проблема-допустимое поведение компилятора. Этот поведение программы, скомпилированной из плохо сформированной, никакой диагностической программы не определяется стандартом: это неопределенное поведение. Носовые демоны разрешены.
необычные попытки (например,sizeof(int[answer])!=sizeof(int[answer])
может, пожалуйста, тег черт компилятор, но не делает вашу программу более хорошо сформированной.
вы можете сделать случай, когда компилятор вряд ли сможет поймать вас на этом, но плохо сформированная-ness остается независимо от способности для компилятора чтобы поймать тебя с ним. Как правило, C++ хочет оставить себе (и своим компиляторам) свободу поиска недопустимого кода шаблона "раньше, чем создание экземпляра"; это означает, что код шаблона должен производить, возможно, юридический код.
возможно, вы хотите что-то вроде =delete
с прикрепленным сообщением.
оба компилятора верны. От [temp.res] / 8:
Если для шаблона не может быть создана допустимая специализация, и этот шаблон не создается, шаблон неправильно сформирован, нет диагностики требуемый.
не существует допустимой специализации, которая может быть создана из основного шаблона Hitchhiker
, поэтому он плохо сформирован, не требуется диагностика. клэнг все равно решает провести диагностику.
Если вы только хотите разрешить 42
, тогда просто не определяйте общий шаблон:
template <int > struct Hitchhiker;
template <> struct Hitchhiker<42> {};