С++ какой тип макроса __FILE__

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

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

         //Here goes the value of the    "given"

     }
};

Использование похожее на

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

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

Ответ 1

__ FILE__ расширяется в строковый литерал, точно так же, как если бы вы написали "/path/to/current/file.cpp" напрямую. Строковые литералы являются немодифицируемыми char массивами lvalues.

Вы хотите, чтобы шаблон, который < вместо использования boost:: any:

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;
    }
};

Ответ 2

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

Ответ 3

__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';
    }
}