С++ какой тип макроса __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';
}
}