C++ __FILE__ 宏的类型是什么?

13

我正在尝试创建一个异常类。为此,我重载了<<运算符。因此,代码大致如下:

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

__FILE__被扩展为一个字符串字面值,就像你直接写入"/path/to/current/file.cpp"一样。 字符串字面值是不可修改的char数组lvalue。

你想使用模板来代替使用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;
    }
};

我必须根据类型使用一些if else条件,例如:如果(输入为no),则输出" line no "和no;如果是字符串,则输出" file name "和fileName。你能说一下如何实现吗? - prabhakaran
@prabhakaran:请确保您查看访问者的答案。尽管我解决了您提到的语法/类型问题,但另一个答案才是正确的语义解决方案。 - Thomas Edleson

8
宏没有类型,它们只是由预处理器进行文本替换(没有类型检查)。由__FILE__插入的值的类型是常量C字符串。

@jdehaan,你能再解释一下吗?C String 是指 CString 还是其他什么? - prabhakaran
3
@Stephane Rolland:const char* 是不正确的,尽管你可以从字符串字面量中获取它。 - Thomas Edleson
一个 C 字符串不是一个类,它是一个常量字面值,就像你直接在源代码中键入 "c:\path\file.cpp" 一样。该字符串字面值的类型是 const char[] - tenfour
2
说“宏没有类型”并不是很有用。一个宏展开后的值是有类型的,就像所有的值一样。 - Jim Balter
@Jim,好评论,那间接地就是我想表达的意思。@Stephane,感谢你的精确说明,我忘记清楚地表达了。 - jdehaan
显示剩余2条评论

5

__FILE__被替换为字符串字面值,其类型为

const char[length_of_particular_string]

你应该认真考虑你正在做什么。(基于你的 前一个问题 的意见)

首先,boost::any 对于这种用法来说不好,特别是由于字符串字面值的类型在不同情况下会有所不同。但即使没有技术上的困难,你也应该使用普通的函数重载。

更重要的是,似乎你想要的功能是接收布尔值,并在该值不为 true 时抛出一个包含文件名和行号的错误。由于你总是需要这 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';
    }
}

非常好的建议,但您可能想将__LINE__更改为__FILE__。 :) - Thomas Edleson
请仅翻译文本内容,不要进行解释。 - prabhakaran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接