Сообщение об ошибке, зная, где оно находится в коде - PullRequest
3 голосов
/ 15 сентября 2011

У меня есть поток с именем "err", который находится в пространстве имен Errors.Вот как разработчик должен сообщать об ошибках в удобной для пользователя форме.Поэтому, когда что-то идет не так, разработчик напишет сообщение об ошибке следующим образом:

Errors::err << "Oh no. That was a bad thing.";

Можно ли использовать препроцессор для добавления [__FILE__:__LINE__] к сообщению об ошибке без изменения текущего стиля сообщения об ошибках?Т.е. вышеприведенная команда теперь (после магии предварительной обработки) выведет это в файл ошибок:

О нет.Это было плохо.[file.cc:20]

Я пробовал это сам, но препроцессор C , похоже, не любит пространства имен, и я не чувствую, что могу пойти на замену«ошибка» везде в коде - что было бы еще более серьезной проблемой, если бы разработчик решил использовать using Errors::err или using namespace Errors.

В рамках того, что я хочу достичь, является C-препроцессорпринципиально несовместим со стилем кодирования?Если да, есть ли другие методы (возможно, основанные на Makefile?), Чтобы делать то, что я хочу?

Ответы [ 2 ]

5 голосов
/ 15 сентября 2011

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

Если вы можете заменить весь код сообщения об ошибках, напримерс

REPORT_ERROR( "Oh no. That was a bad thing." );

это было бы легко.Вы бы просто #define макрос

#define REPORT_ERROR(x) Errors::err << x << "[" << __FILE__ << ":" << __LINE__ << "]" << endl;
4 голосов
/ 15 сентября 2011

Ну вот, думаю, это работает. Вы должны заметить, что делать это может быть плохой идеей, потому что этот код в лучшем случае фанк, прямо ошибочным или в худшем случае некорректным. Я не проверял и не проверял это глубоко, но я знаю, что он компилируется и работает в моей системе (Windows 7 / MSVC10). Если бы я увидел что-то подобное в рабочем коде, я бы, вероятно, посчитал это хаком, и в противном случае мне бы пришлось убедиться в этом.

Наслаждайтесь.

#include <cstdlib>
#include <sstream>
#include <string>
#include <iostream>
using namespace std;

namespace Errors
{
    class errstream
    {
    public:
        errstream(const std::string& filename, int lineno) : file_(filename), line_(lineno) {};
        std::string dump() const;
        errstream& operator<<(const std::string& msg)
        {
            cout << msg << "\t[" << file_ << ":" << line_ << "]";
            return * this;
        }
    private:
        std::string file_;
        int line_;
    };
};

 #define err errstream(__FILE__, __LINE__)

int main()
{
    Errors::err << "Oh no. That was a bad thing.";
}

Вывод (для меня):

О нет. Это было плохо. [Main.cpp: 30]

РЕДАКТИРОВАТЬ: КРУГЛЫЙ 2

В комментариях ниже было указано новое требование. ОП хотел иметь возможность сделать что-то вроде этого:

Errors::err << "File Not Found '" << file << "'  What A Bummer. :(";

... и иметь вывод:

Файл не найден! 'foo.txt' Какой облом. :( [файл: nnn]

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

Файл не найден! '[main.cpp: 61] foo.txt [main.cpp: 61]' Что за облом. :( [main.cpp: 61]

Этого можно добиться, если errstream вывести свое содержимое в cout при вызове деструктора, а не при вызове оператора вставки потока. Оператор вставки потока, в свою очередь, somply собирает токены, которые будут выгружены в cout перед строкой местоположения. Новый код:

#include <cstdlib>
#include <sstream>
#include <string>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;

namespace Errors
{
    class errstream
    {
    public:
        errstream(const std::string& filename, int lineno) : file_(filename), line_(lineno) {};
        ~errstream()
        {
            std::copy(tokens_.begin(), tokens_.end(), ostream_iterator<string>(cout));
            cout << "\t[" << file_ << ":" << line_ << "]\n";
        }
        errstream& operator<<(const std::string& msg)
        {
            tokens_.push_back(msg);
            return *this;
        }
    private:
        typedef std::vector<std::string> Tokens;
        Tokens tokens_;
        std::string file_;
        int line_;
    };
};

 #define err errstream(__FILE__, __LINE__)

int main()
{
    Errors::err << "Oh no. That was a bad thing.";

    string file = "foo.txt";
    Errors::err << "File not found! '" << file << "' What a bummer. :(";

}

Вывод теперь:

О нет. Это было плохо. [main.cpp: 38]

Файл не найден! 'foo.txt' Какой облом. :( [main.cpp: 41]

...