Я использую g ++ 4.6.3 (в настоящее время это пакет по умолчанию для ubuntu 12.04) с флагом c ++ 0x, и я натыкаюсь на это:
template <typename T>
inline T getValue(AnObject&)
{
static_assert(false , "this function has to be implemented for desired type");
}
с ошибкой компиляции:
static_assertion failed "this function has to be implemented for the desired type"
хотя я еще нигде не вызываю эту функцию.
Это ошибка G ++? Эта функция не должна создаваться только в том случае, если она вызывается где-то в коде.
Это потому, что условие никак не зависит от параметров шаблона. Следовательно, компилятор может оценить его еще до создания экземпляра этого шаблона и выдает соответствующее сообщение об ошибке компиляции, если это дает оценка false
,
Другими словами, это не ошибка. Хотя многие вещи могут быть проверены только после создания экземпляра шаблона, существуют другие проверки достоверности, которые компилятор может выполнить даже раньше. Вот почему в C ++, например, есть двухфазный поиск имен. Компилятор просто пытается помочь вам найти ошибки, которые могут возникнуть на 100%.
Стандарт говорит в [temp.res] / 8
Не должно быть выдано никакой диагностики для определения шаблона, для которого может быть сформирована действительная специализация. Если для определения шаблона не может быть сгенерировано никакой действительной специализации, и этот шаблон не создан, определение шаблона неверно, диагностика не требуется. … [ Заметка: Если шаблон создан, ошибки будут диагностированы в соответствии с другими
правила в этом стандарте. Именно тогда, когда эти ошибки диагностируются, возникает проблема качества реализации. — конец примечания]
Невозможно создать экземпляр шаблона вашей функции, который будет компилироваться, поэтому определение шаблона неправильно сформировано, и поэтому компилятору разрешено (но не обязательно) отклонить его, даже если он не создан.
Вы можете заставить его работать так:
template<typename T>
struct foobar : std::false_type
{ };
template <typename T>
inline T getValue(AnObject&)
{
static_assert( foobar<T>::value , "this function has to be implemented for desired type");
}
Теперь компилятор не может сразу отклонить шаблон функции, потому что пока он не будет создан, он не знает, будет ли специализация foobar
который имеет value == true
, При создании соответствующей специализации foobar<T>
будет создан, и статическое утверждение все равно не будет выполнено, как хотелось бы.
Это действительно комментарий, но требуется пример кода.
Священный стандарт формулировка static_assert
не ограничивает его действие созданным кодом.
Тем не менее, код
template <typename T>
inline T getValue(int&)
{
typedef char blah[-1]; // Common C++03 static assert, no special semantics.
}
int main()
{}
также не удается скомпилировать с MinGW g ++ 4.7.2, что подчеркивает вопрос.
я считать ответ заключается в том, что g ++ верен, а Visual C ++ 11.0, который не приводит к ошибке компиляции, неверен, но мне было бы сложно дать соответствующий анализ в терминах стихов Священного Стандарта.
Практическим следствием разницы в компиляторе является то, что в настоящее время вы не можете полагаться на поведение.