Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
template_metaprogramming_ru.docx
Скачиваний:
12
Добавлен:
01.07.2025
Размер:
774 Кб
Скачать
☆

Инструменты

Самыми трудноразборчивыми ошибками при диагностике шаблонов являются глубоко вложенные шаблонные инстанцирования.

Правило:

Чем раньше обнаружена ошибка, тем с меньшими усилиями ее можно исправить.

Масштабные сообщения об ошибках времени компиляции гораздо лучше тихого исполнения программы с возможным падением от срабатывания assert утверждений.

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

Например, мы могли бы попытаться скомпилировать:

#include <algorithm>

#include <list>

int main()

{

std::list<int> x;

std::sort(x.begin(), x.end());

}

В идеале компилятор должен сообщать о проблеме в момент фактической ошибки программы, а также предоставлять информацию о абстракции итераторов, как в этом случае:

main.cpp(7) : std::sort requires random access iterators, but

std::list<int>::iterator is only a bidirectional iterator

В MSVC7.1 отчет выглядит следующим образом:

C:\Program Files \Microsoft Visual Studio .NET 2003\Vc7 \include\

algorithm(1795) : error C2784:

'reverse_iterator<_RanIt>::difference_type std::operator -(const

std::reverse_iterator<_RanIt> &,const

std::reverse_iterator<_RanIt> &)' : could not deduce template

argument for 'const std::reverse_iterator<_RanIt> &' from

'std::list<_Ty>::iterator'

with

[

_Ty=int

]

continued...

Сообщается об ошибке в некотором операторе стандартной библиотеке в заголовке <algorithm>, вместо того, чтобы сообщить об ошибке в теле функции main(), где она фактически произошла. Причина: проблема сокрыта из-за появления std::reverse_iterator, который не имеет никакого очевидного отношения к написанному коду. Даже использование оператора, который «намекает» на потребность в итераторах произвольного доступа, непосредственно не связано с тем, что программист пытался на самом деле сделать. Если бы несоответствие между итертором std::list <int>::iterator и требованием std::sort в итерторе произвольного доступа было обнаружено ранее (идеально в точке вызова std::sort), то компилятор смог бы сообщить о проблеме максимально точно.

Проблема плохих сообщений в ошибках – это не вина компилятора, фактически, это происходит из-за ограничения языка C++. Если сигнатуры обычных функций четко указывают типы допустимых аргументов, то для обобщенных функций такой ясности нет. При этом, у авторов библиотеки есть механизмы, как ограничить ущерб, наносимый ошибкой. Эти подходы позволяют генерировать диагностику заранее и в большей степени контролировать содержание сообщений об ошибках.

Несколько компиляторов

Советы:

  • Использовать несколько различных компиляторов в отладочных целях.

Использование пост-процессорной обработки, с помощью следующих приложений (TextFilt (http://textfilt.sourceforge.net) или STLFilt (http://www.bdsoft.com/tools/stlfilt.html). Их основные возможности включают в себя автоматическую элизию аргументов по умолчанию из специализаций известных шаблонов, и typedef замены std::string и std::wstring.

Например, TextFilt может преобразовать следующие сообщения:

example.cc:21: conversion from 'double' to non-scalar type

'map<vector<basic_string<char, string_char_traits<char>,

__default_alloc_template<true, 0> >,

allocator<basic_string<char, string_char_traits<char>,

__default_alloc_template<true, 0> > > >, set<basic_string<char,

string_char_traits<char>, _ _default_alloc_template<true, 0> >,

less<basic_string<char, string_char_traits<char>,

__default_alloc_template<true, 0> > >,

allocator<basic_string<char, string_char_traits<char>,

__default_alloc_template<true, 0> > > >,

less<vector<basic_string<char, string_char_traits<char>,

__default_alloc_template<true, 0> >,

allocator<basic_string<char, string_char_traits<char>,

__default_alloc_template<true, 0> > > > >,

allocator<set<basic_string<char, string_char_traits<char>,

__default_alloc_template<true, 0> >, less<basic_string<char,

string_char_traits<char>, _ _default_alloc_template<true, 0> > >,

allocator<basic_string<char, string_char_traits<char>,

__default_alloc_template<true, 0> > > > > >' requested

в следующее:

example.cc:21: conversion from 'double' to non-scalar type

'map<vector<string>,set<string>>' requested

Редактировкани сообщений об ошибка в среде GCC:

Есть два варианта для изменения порядка сообщение GCC:

  • hdr: LD1: переносит сообщение об ошибке в начало следа трассировки;

  • hdr: LD2: подобен hdr:LD1, но добавляет копию последней строке трассировки (не-шаблонный код, который привел к инициированию) только после сообщения об ошибке.

Обертки для выражений и идентификация:

Прблемными местами для фильтрации сообщений являются составные типы и выражения – с вложенными элементами. STLFilt включает в себя мета опцию, которая форматирует сообщения метапрограммных компонентов. Даже с пропуском шаблонных параметров по умолчанию и отключенными переопределениями typdef, STLFilt может помочь в разборе сообщения:

example.cc:21: conversion from 'double' to non-scalar type

'map<

vector<

basic_string<

char, string_char_traits<char>

, __default_alloc_template<true, 0>

>, allocator<

basic_string<

char, string_char_traits<char>

, __default_alloc_template<true, 0>

>

>

>, set<

basic_string<

char, string_char_traits<char>

, __default_alloc_template<true, 0>

>, less<

basic_string<

char, string_char_traits<char>

, __default_alloc_template<true, 0>

>

>, allocator<

basic_string<

char, string_char_traits<char>

' __default_alloc_template<true, 0>

>

>

>, less<

...12 lines omitted...

>, allocator<

...16 lines omitted...

>

>' requested

Хоть сообщение все еще огромно, но зато стало намного более читаемым: его первые несколько столбцов позволяют понять, что типом является map, состоящий из vector <string> и set <string>.

Настройка параметров командной строки в www.bdsoft.com/tools/stlfiltopts.html.

Static Assertions

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]