C++what is the type of the __FILE__ macro
I am trying to create an exception class. For this I overloaded the <<
operator. So the code is something like this
class 开发者_运维百科RunAndCheck
{
opearator << (boost::any given)
{
//Here goes the value of the "given"
}
};
The usage is like this
RunAndCheck s;
s << file->open() << __FILE__ << __LINE__ ;
So the problem is that I want to know the type of the FILE, then only I can extract the string out of boost::any
. Can anybody invoke your curiosity around this?
__FILE__ expands into a string literal, just as if you had written "/path/to/current/file.cpp" directly. String literals are non-modifiable char array lvalues.
You want to template that << instead of using boost::any:
class RunAndCheck {
public:
template<class T>
RunAndCheck& operator<<(const T& value) {
// ...
return *this;
}
};
Or you want to provide overloads for all the acceptable types:
class RunAndCheck {
public:
RunAndCheck& operator<<(const char* value) {
// ...
return *this;
}
RunAndCheck& operator<<(int value) {
// ...
return *this;
}
};
Macros do not have types, they are just text replacements made by the preprocessor (without type checks). The type of the value dropped in by __FILE__
is a constant C string.
__FILE__
is replaced by a string literal, whose type is
const char[length_of_particular_string]
You should really reconsider what you are doing. (Opinion also based on your previous question.)
Firstly, boost::any is no good for such usage (in particular since the type of the string literal will be different in different cases). But even if not for the technical difficulties, you should use normal function overloading.
More importantly, it seems that the functionality that you want is to receive a boolean value and throw an error containing the file name and line number if the value is not true. Since you always require all 3 components (although according to your description it would be possible to have it throw without giving it the file name, or have the class do nothing useful), a function that takes those 3 arguments makes more sense.
Furthermore, you can now wrap calls to this in a macro, so that the file name and line number are automatically provided.
Full example:
#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';
}
}
精彩评论