我正在尝试创建一个异常类。为此,我重载了<<
运算符。所以代码是这样的
class RunAndCheck
{
opearator << (boost::any given)
{
//Here goes the value of the "given"
}
};
用法就像这样
RunAndCheck s;
s << file->open() << __FILE__ << __LINE__ ;
所以问题是我想知道 FILE 的类型,然后我只能从boost::any
中提取字符串。任何人都能引起你的好奇吗?
答案 0 :(得分:11)
__ FILE__扩展为字符串文字,就像你直接写了“/path/to/current/file.cpp”一样。字符串文字是不可修改的字符数组左值。
你想模板&lt;&lt;而不是使用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;
}
};
答案 1 :(得分:8)
宏没有类型,它们只是预处理器所做的文本替换(没有类型检查)。 __FILE__
下降的值的类型是常量C字符串。
答案 2 :(得分:3)
__FILE__
被字符串文字替换,其类型为
const char[length_of_particular_string]
你应该重新考虑你在做什么。 (意见也基于您的previous question。)
首先,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';
}
}