C ++, какой тип макроса __FILE__ - PullRequest
12 голосов
/ 21 февраля 2011

Я пытаюсь создать класс исключений.Для этого я перегрузил оператор <<.Таким образом, код выглядит примерно так:

class RunAndCheck
{
     opearator << (boost::any given)
     {

         //Here goes the value of the    "given"

     }
};

Использование выглядит примерно так:

RunAndCheck s;
s << file->open() << __FILE__ << __LINE__ ; 

Итак, проблема в том, что я хочу знать тип FILE только тогда я могу извлечь строку из boost::any.Кто-нибудь может вызвать ваше любопытство по этому поводу?

Ответы [ 3 ]

11 голосов
/ 21 февраля 2011

__ FILE__ расширяется до строкового литерала, как если бы вы написали "/path/to/current/file.cpp" напрямую. Строковые литералы являются неизменяемыми символьными массивами lvalues.

Вы хотите создать шаблон << вместо использования boost :: any: </p>

class RunAndCheck {
public:
    template<class T>
    RunAndCheck& operator<<(const T& value) {
        // ...
        return *this;
    }
};

Или вы хотите предоставить перегрузки для всех допустимых типов:

class RunAndCheck {
public:
    RunAndCheck& operator<<(const char* value) {
        // ...
        return *this;
    }
    RunAndCheck& operator<<(int value) {
        // ...
        return *this;
    }
};
8 голосов
/ 21 февраля 2011

Макросы не имеют типов, это просто текстовые замены, сделанные препроцессором (без проверки типов).Тип значения, вставленного на __FILE__, является константной строкой C.

4 голосов
/ 21 февраля 2011

__FILE__ заменяется строковым литералом, тип которого

const char[length_of_particular_string]

Вы должны действительно пересмотреть то, что вы делаете.(Мнение также основано на вашем предыдущем вопросе .)

Во-первых, boost :: any не годится для такого использования (в частности, поскольку тип строкового литерала будет отличаться в разных случаях).Но даже если бы не технические трудности, вам следует использовать обычную перегрузку функций.

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

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

Полный пример:

#include <stdexcept>
#include <sstream>
#include <iostream>

void check_result(bool result, const char* line, int line_number)
{
    if (!result) {
        //for example:
        std::stringstream ss;
        ss << line << ' ' << line_number;
        throw std::runtime_error(ss.str()); 
    } 
} 

#define CALL_AND_CHECK(expression) check_result((expression), __FILE__, __LINE__)

bool foobar(bool b) { return b; }

int main()
{
    try {
        CALL_AND_CHECK(foobar(true));
        CALL_AND_CHECK(foobar(false));
    } catch (const std::exception& e) {
        std::cout << e.what() << '\n';
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...