Шаблоны C ++ известны тем, что генерируют длинные нечитаемые сообщения об ошибках. У меня есть общее представление о том, почему сообщения об ошибках шаблона в C ++ такие плохие. По сути, проблема в том, что ошибка не вызывается до тех пор, пока компилятор не обнаружит синтаксис, который не поддерживается определенным типом в шаблоне. Например:
template <class T>
void dosomething(T& x) { x += 5; }
Если оператор T
не поддерживает +=
, компилятор сгенерирует сообщение об ошибке. И если это происходит где-то глубоко внутри библиотеки, сообщение об ошибке может быть длиной в тысячи строк.
Но шаблоны C ++, по сути, всего лишь механизм для утки во время компиляции. Ошибка шаблона C ++ концептуально очень похожа на ошибку типа времени выполнения, которая может возникнуть в динамическом языке, таком как Python. Например, рассмотрим следующий код Python:
def dosomething(x):
x.foo()
Здесь, если x
нет foo()
метода, интерпретатор Python генерирует исключение и отображает трассировку стека вместе с довольно четким сообщением об ошибке, указывающим на проблему. Даже если ошибка не сработает до тех пор, пока интерпретатор не окажется глубоко внутри какой-либо библиотечной функции, сообщение об ошибке времени выполнения все равно не так плохо, как нечитаемая рвота, извергаемая типичным компилятором C ++. Так почему же компилятор C ++ не может быть более ясным о том, что пошло не так? Почему некоторые сообщения об ошибках шаблона C ++ буквально вызывают прокрутку окна моей консоли более 5 секунд?
источник
clang++
подмигнул).Ответы:
Шаблонные сообщения об ошибках могут быть печально известными, но далеко не всегда длинными и нечитаемыми. В этом случае полное сообщение об ошибке (из gcc):
Как и в вашем примере с Python, вы получаете «трассировку стека» точек создания шаблона и четкое сообщение об ошибке, указывающее на проблему.
Иногда сообщения об ошибках, связанных с шаблоном, могут быть намного длиннее по разным причинам:
Основным отличием от Python является статическая система типов, что приводит к необходимости включения (иногда длинных) имен типов в сообщение об ошибке. Без них иногда было бы очень трудно диагностировать, почему не удалось разрешить перегрузку. С ними ваша задача больше не угадать, где проблема, а расшифровать иероглифы, которые говорят вам, где она.
Кроме того, проверка во время выполнения означает, что программа остановится при первой обнаруженной ошибке, отображая только одно сообщение. Компилятор может отображать все ошибки, с которыми он сталкивается, пока он не сдастся; по крайней мере в C ++ он не должен останавливаться на первой ошибке в файле, поскольку это может быть следствием более поздней ошибки.
источник
Вот несколько очевидных причин:
Это далеко не исчерпывающий, но вы получите общее представление. Даже если это не так просто, большинство из них можно вылечить. В течение многих лет я говорил людям, чтобы получить копию Comeau C ++ для регулярного использования; Я, вероятно, сохранил достаточно от одного сообщения об ошибке один раз, чтобы заплатить за компилятор. Теперь Clang добирается до той же точки (и это даже дешевле).
Я закончу общим наблюдением, которое звучит как шутка, но на самом деле это не так. Честно говоря, настоящая работа компилятора - превращать исходный код в сообщения об ошибках. Пришло время, чтобы поставщики сконцентрировались на том, чтобы выполнять эту работу немного лучше - хотя я открыто признаю, что когда я писал компиляторы, у меня была сильная тенденция относиться к нему как к вторичному (в лучшем случае), а в некоторых случаях почти игнорировал его полностью.
источник
Простой ответ заключается в том, что Python был разработан для такой работы, тогда как многие вещи, связанные с шаблонами, возникли случайно. Например, она никогда не предназначалась для того, чтобы стать полной по Тьюрингу системой. И если вы не можете сознательно планировать и рассуждать о том, что происходит, когда ваша система работает , зачем кому-то ожидать тщательного, вдумчивого планирования того, что происходит, когда что-то идет не так?
Кроме того, как вы указали, интерпретатор Python может упростить вам задачу, отображая трассировку стека, поскольку он интерпретирует код Python. Если компилятор C ++ обнаружит ошибку шаблона и выдаст трассировку стека, это будет так же бесполезно, как и «шаблонная рвота», не так ли?
источник