2016-07-05 6 views
1

Этот вопрос частично ответил: решение заключается в том, что в одном из полей моего класса, в частности _escape, есть UB. Однако до сих пор неизвестно, почему в трассировке стека Visual Studio не отображается оператор < <, и отладчик не находит его - почти как если бы была оптимизация (отключена оптимизация), чтобы удалить символ и объединить его с функцией печати.При переопределении оператора << (поток) отладка переходит в std вместо << impl вместо этого?

То, что я уже знаю,

Я видел все популярные сообщения на SO о < < перегрузки оператора. Я следовал всей основной семантике. Это не дублирующий вопрос о любой из популярных сообщений.

Для переопределения оператора < <, нужно определить функцию с общим форматом:

ostream& operator<<(ostream& os, const MyObject& dt) 

я сделал это в моей программе,

Я использую Microsoft Visual Studio 2015 для этого проекта, и используя отладчик, чтобы попытаться выполнить функцию оператора < <. Тем не менее, он никогда не попадает внутрь функции, которую я определил следующим образом:

std::ostream& operator <<(std::ostream& os, const EscapeStr& t) 
{ 
    t.print(os); 
    return os; 
} 

где EscapeStr класс I определяется следующим определением функции для print:

void print(std::ostream& os) const { 
    for (int i = 0; i < _elem.length(); i++) { 
     char c = _elem[i]; 
     if (_delim[c]) { 
      for (int j = 0; j < _escLen; j++) { 
       os << _escape[j]; 
      } 
     } 
     os << _elem[i]; 
    } 
} 

Проблема

Я вижу функцию print(), вызываемую здесь, используя отладчик VS, но я не могу наблюдать, как программа вводит область моего переопределенного < <, но скорее она входит в определение std < <, со следующей подписью:

template<class _Traits> inline 
    basic_ostream<char, _Traits>& operator<<(
     basic_ostream<char, _Traits>& _Ostr, 
     const char *_Val); // insert NTBS into char stream 

Это очень странно, потому что только оператор ostream переопределения имеет доступ к моей общественной функции в настоящее время. Является ли Visual Studio просто лживым?

Я не понимаю, что происходит, как один из моих других перегрузок сделать работу, а подпись не является даже точной (без сопзЬ и ссылки):

/// ostream operator for indent 
std::ostream& operator <<(std::ostream &os, indent x) 
{ 
    static const std::string spaces(" "); 
    while(x.d--) { 
     os << spaces; 
    } 
    return os; 
} 

В результате, мой программа демонстрирует некоторые UB (чтение кода библиотеки std приведет меня в бешенство). Вот идеон, чтобы показать UB: https://ideone.com/jxro5s. Любая помощь будет принята с благодарностью.

Дополнительная информация для MVCE и ясности

const static char _delims[] = { '\\', '"' }; 
const static std::vector<char> delims(_delims, _delims + 2); 

class EscapeStr { 
    const static unsigned short MAX_CHAR = 256; 

    std::string &_elem; 
    bool _delim[MAX_CHAR]; 
    const char* _escape; 
    int _escLen; 
public: 
    EscapeStr(std::string &elem, 
     const std::vector<char> &delim = std::vector<char>(1, '"'), 
     const std::string &escape = "\\") : 
     _elem(elem), 
     _escape(escape.c_str()), 
     _escLen(escape.size()) 
    { 
     for (int i = 0; i < MAX_CHAR; i++) { 
      _delim[i] = false; 
     } 
     for (int i = 0; i < delim.size(); i++) { 
      _delim[delim[i]] = true; 
     } 
    } 
    void print(std::ostream& os) const { 
     for (int i = 0; i < _elem.length(); i++) { 
      char c = _elem[i]; 
      if (_delim[c]) { 
       for (int j = 0; j < _escLen; j++) { 
        os << _escape[j]; 
       } 
      } 
      os << _elem[i]; 
     } 
    } 
}; 

Вот изображение трассировки стека - никаких признаков оператора < <.

EDIT: Предсказывать будущие комментарии/сообщения обо мне, не используя std :: quoted - Я пытаюсь сделать программу совместимой с версиями менее C++ 11.

+0

Если вызывается 'print()', то, безусловно, вы вызываете ваш переопределенный 'operator <<'? Кроме того, ваш 'operator <<' должен быть объявлен 'const'. – ArchbishopOfBanterbury

+0

Похоже, у вашего класса есть оператор литья, который вызывается для преобразования 'EscapeStr' в' char const * '. Скорее всего, ваша функция 'operaro <<' не объявляется в то время, когда вы ее вызываете. –

+0

@ArchbishopOfBanterbury Я тоже так думаю, но я поставил точки останова на каждую строку этой перегрузки оператора и никогда не входил. – OneRaynyDay

ответ

3

Я думаю, что первое, что нужно сделать, это исправить неопределенное поведение чтения от _escape после того, как временная строка, на которую были удалены точки. Лучший вариант, на мой взгляд, заключается в том, чтобы заменить const char* _escape; int _escLen; на std::string escape_;, а затем ваш цикл for станет os << escape_;. Поскольку мы говорим о UB здесь, все может произойти, в том числе не называть ваш пользовательский operator<<.

+0

Ах, ты прав. Я забыл эту ошибку, так как я был так сосредоточен на попытке заставить «оператор <<» работать. Я исправлю это и отчитаю результаты. Спасибо за улов! РЕДАКТИРОВАТЬ: Исправлено, но я до сих пор не вижу оператора <<, входящего в мою функцию. Тем не менее, выход такой же, как ожидалось. Это может быть проблема с визуальной студией? Я оставлю этот вопрос открытым в течение небольшого времени, чтобы побудить вас обсуждать отладчик визуальной студии, но я, скорее всего, приму ваш ответ, так как он исправил мой вывод. – OneRaynyDay