Как вы отлаживаете сильно шаблонный код в C ++? - PullRequest
22 голосов
/ 19 февраля 2009

Мне очень трудно понять, что не так с моим кодом при использовании метапрограммирования на С ++. Возможно, я просто не очень хорошо разбираюсь в сообщениях об ошибках, но, насколько мне известно, я не могу прибегнуть к использованию операторов печати или точек останова, чтобы выяснить, что происходит.

Какие советы или рекомендации вы можете предложить, пытаясь выяснить, почему что-то не компилируется, кроме как просто просмотреть код вручную и надеяться, что он придет ко мне?

Ответы [ 10 ]

14 голосов
/ 19 февраля 2009

По крайней мере, для STL есть инструменты, которые выводят более понятные сообщения об ошибках. Смотри http://www.bdsoft.com/tools/stlfilt.html

Для не-STL шаблонов вам просто нужно узнать, что означают ошибки. После того, как вы видели их дюжину раз, становится легче угадать, в чем проблема. Если вы разместите их здесь, возможно, кто-то может помочь вам разобраться.

7 голосов
/ 19 февраля 2009

Вы можете попробовать использовать более новый компилятор. Если вы используете Visual C ++ 6.0, переключитесь на 9.0, и вы увидите огромный скачок в полезности ошибок компилятора.

В противном случае мои приемы обычно заключались в том, чтобы тестировать как можно меньшую часть кода, пока я не изолирую ошибки. Это, вероятно, самая большая ошибка системы шаблонов - разумного способа их отладки нет.

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

5 голосов
/ 19 февраля 2009

Если вы используете gcc, я обнаружил, что colorgcc может помочь немного. Цветовое кодирование облегчает умственный анализ предупреждений, ошибок и контекстной информации.

4 голосов
/ 19 февраля 2009

При создании чего-то сложного в языке метапрограммирования я использую макрос BOOST_MPL_ASSERT несколько раз, проверяя результаты каждого шага мета-выполнения. Библиотека Boost.MPL очень полезна в этом отношении. Я предлагаю вам использовать оттуда как можно больше кода, потому что он, скорее всего, не будет содержать ошибок.

Когда я не уверен, что используется правильная специализация для класса, я склонен выделять правильную специализацию в пространстве имен. Если вы уверены, что специализация действительна, вы должны убедиться, что она выбрана. Если это не так, вы должны выяснить, какой из них выбран на своем месте. Тогда я бы порекомендовал использовать Boost.EnableIf, чтобы исключить эту ошибочно принятую специализацию из процесса выбора.

И последнее, но не менее важное: STLfilt чрезвычайно полезен, и вы можете изменить его самостоятельно, чтобы он максимально соответствовал вашим потребностям.

Но самое главное - стараться не использовать метапрограммирование везде . Это сложно, поэтому используйте его только тогда, когда это действительно нужно .

3 голосов
/ 19 февраля 2009

Какой компилятор вы используете? VC8 и 9 на самом деле довольно приличны в выводе читаемых сообщений об ошибках. Это все еще требует некоторого терпения, но это может быть сделано, и они по существу показывают эквивалент времени компиляции стека вызовов. Начиная снизу, какой экземпляр шаблона вызвал ошибку, и каковы были аргументы шаблона? Следующий уровень вверх показывает шаблон, с которого он был создан, и так далее, вплоть до верхнего уровня. Конечно, это видно только на вкладке «output», а не на «ошибках», которые обычно отображаются после неудачной компиляции.

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

Это боль, но это можно сделать, и для этого требуется только терпение и готовность прочитать сообщения об ошибках. :)

Кроме того, либеральное использование static_assert (или BOOST_STATIC_ASSERT) может очень помочь, предоставляя проверки работоспособности

3 голосов
/ 19 февраля 2009

Это должно помочь вам, я думаю.

http://www.bdsoft.com/tools/stlfilt.html

Я сам этим не пользовался; но это может помочь вам. Я также могу сказать вам, что по мере того, как вы будете получать больше опыта с шаблонами и метапрограммами, вы привыкнете к сообщениям об ошибках. Иногда их бывает сложно читать; но в их безумии есть логика. Просто сделайте ваш терминал как можно большим и попробуйте перевести то, что он говорит, в вашей голове, когда вы читаете его.

2 голосов
/ 21 февраля 2009

Как уже показывают ответы, в шаблонном коде есть два типа трудностей: 1. заставить его скомпилировать и найти причину ошибок компилятора 2. заставить его делать правильные вещи во время выполнения

Обычно я пытаюсь отделить магию типа времени компиляции от логики времени выполнения, это помогает найти причину проблемы (тип 1 или 2). Чтобы достичь этого, используйте один тип шаблона для магии типов и как можно меньше функциональности во время выполнения и один простой тип для логики времени выполнения, который использует тип шаблона.

Если вы затем последуете советам из других ответов, особенно из тех, что утверждают в compile_time, вам будет легче найти источник проблемы.

2 голосов
/ 19 февраля 2009

Вы привыкнете к этому с течением времени, и, к сожалению, если вы планируете использовать C ++, вам придется. Потому что некоторые библиотеки, такие как VC9, имеют хорошие сообщения об ошибках, но как только вы переходите к GCC или другому компилятору, сообщения исчезают. И даже VC9 не очень вам поможет, если у вас есть ошибки из какой-то библиотеки, написанной кем-то другим или вами самим поздно вечером, даже некоторые библиотеки Boost не настолько дружелюбны. Просто потому, что не каждый автор приложил все усилия, чтобы прояснить ситуацию при возникновении ошибки, и это еще чаще встречается в новых библиотеках (которые, как правило, содержат больше ошибок и меньше помогают).

Также вы должны помнить, что хорошие STATIC_ERRORS, которые вы можете найти здесь и там в коде, размещаются авторами там, где что-то обычно ломается, и всегда будут ужасные угловые случаи, которые автор не рассматривал, которые приведут 400 строк сообщений об ошибках, потому что вы где-то пропустили const, например.

Использование инструментов вначале поможет вам, но в конечном итоге навредит вам. И поскольку проблема присуща C ++, она не исчезнет в ближайшее время. И эти стены ошибок, вероятно, будут с нами, пока C ++ больше не используется. Так что инструменты будут просто резать зубы, когда они понадобятся, чтобы выжить. Если вы планируете вскоре покинуть C ++, пожалуйста, не стесняйтесь использовать их. В настоящее время я обычно могу понять эти 400-строчные сообщения об ошибках одним взглядом, поэтому они предельно ясны для меня, но это не благодаря каким-либо инструментам.

Как и все, особенно C ++, требуется опыт и обучение.

1 голос
/ 12 декабря 2014

Templight : отладчик и профилировщик метапрограмм шаблона C ++

0 голосов
/ 13 марта 2017

Metashell - отличный инструмент для отладки шаблонов. С онлайн режимом!

...