如何检查是否可以使用__PRETTY_FUNCTION__?

8

...../PluginLoader.h:34: 'Dummy_Func_For_Generating_FUNCTION_NAME_Macro()'存在多次定义

以上错误是由下面的代码引起的。我在文件中使用了include guards,并且其他所有内容都编译正常。

编辑:我的目标是检查是否定义了__PRETTY_FUNCTION__,如果定义了,通过FUNCTION_NAME宏在后面的代码中使用它(用于日志记录)。如果未定义__PRETTY_FUNCTION__,则使用下一个最佳选择等。但是,我得到的回复让我意识到这是不可能的。那么,如果__PRETTY_FUNCTION__和所有这些其他内容都不是宏,它们是什么?如何检查某个实现是否具有其中之一?

    void Dummy_Func_For_Generating_FUNCTION_NAME_Macro()
    {
#ifndef FUNCTION_NAME
    #ifdef __PRETTY_FUNCTION__
        #define FUNCTION_NAME __PRETTY_FUNCTION__
    #elif __FUNCTION__
        #define FUNCTION_NAME __FUNCTION__
    #elif __func__
        #define FUNCTION_NAME __func__
    #else
        #define FUNCTION_NAME ""
    #endif
#endif
    }

@Adrien:这些是预定义的宏,但并非所有编译器都实现了全部。 - Paul R
1
你把这个函数放在头文件里了吗?如果头文件被多次包含,编译器可能会抱怨发现同一个函数出现了多次。 - Patrick
4
询问目标而非步骤。如果别人不了解你的意图,就无法帮助你。所以,“这里有什么问题”相当于“谁知道呢?你告诉我们吧。”据我所知,你的目标是生成编译错误,这里没有问题。 - GManNickG
1
@GMan: 我并不是想制造编译器错误。我只是想正确地定义 FUNCTION_NAME。而且,我已经在标题中清楚地问了我的问题。 - nakiya
@nakiya:解决方案在我的答案中。使用“_MSC_VER”来识别“__FUNCTION__”。相应地处理所有其他编译器。 - Dialecticus
显示剩余6条评论
4个回答

14

void Dummy_Func_For_Generating_FUNCTION_NAME_Macro()是一个函数,不是宏。函数不会创建宏。宏在预处理阶段解析,而函数在编译器阶段解析。移除函数定义,只保留#ifndef块。

使用编译器识别的宏来确定要使用哪个函数标识宏。例如:

#ifdef _MSC_VER // Visual Studio
    #define FUNCTION_NAME __FUNCTION__
#endif

2
@Dialecticus:我只是确保FUNCTION_NAME被定义了。正因为预处理器在编译器之前运行,所以我可以知道要使用哪个宏。 - nakiya
+1:这个答案非常准确。删除函数即可。由于您将其放在没有内联的头文件中,因此它是多重定义的。我认为,答案中描述的方法是完美的解决方案 :) - Goz
@Goz:那么,如果我将函数内联,错误会消失吗?我不打算使用那个方法,只是想知道。为什么会这样? - nakiya
kriss的回答解释了__FUNCTION__不是真正的预处理器宏。它在编译时定义,而不是在预处理时定义。预处理器无法识别它。 - Dialecticus
Kriss的回答是你问题的实际答案。我只是试图给你一个你真正应该问的问题的答案。 - Dialecticus
显示剩余7条评论

5

__PRETTY_FUNCTION____FUNCTION__不像__LINE____FILE__那样是预处理器宏,而是魔法常量。它们在预处理器阶段不可用,只有在编译时(在函数作用域内)才能使用。

因此,无论您在这里尝试使用的宏是什么,都可能无法正常工作。

然而,编译错误可能是守卫的问题。我成功编译了一个与下面稍有不同的程序(请参见下文),没有任何问题。但是如上所述,FUNCTION_NAME将始终设置为空字符串。

xx.h头文件

#ifndef H_XX_H
#define H_XX_H

#ifndef FUNCTION_NAME
    void Dummy_Func_For_Generating_FUNCTION_NAME_Macro()
    {
    #ifdef __PRETTY_FUNCTION__
        #define FUNCTION_NAME __PRETTY_FUNCTION__
    #elif __FUNCTION__
        #define FUNCTION_NAME __FUNCTION__
    #elif __func__
        #define FUNCTION_NAME __func__
    #else
        #define FUNCTION_NAME ""
    #endif
   ;
   }
#endif
#endif

xx.c源代码文件

#include <stdio.h>
#include "xx.h"

main(){
    printf("%s\n", FUNCTION_NAME);
}

__GUARD 是保留的,不要使用它 - GManNickG
好的,我猜你不是在关注__guard关键字,而是双下划线。 - kriss
+1,我没有意识到__PRETTY_FUNCTION__等常量直到编译时才被初始化,在回顾时,这似乎是显而易见的 :) - Gearoid Murphy

0

我以前遇到过这个问题,是由于挂载的磁盘引起的:

subst R: C:\Source\

Test.cpp:

 #include "C:\Source\PluginLoader.h"  
 #include "R:\PluginLoader.h"

现在,如果你使用 #pragma once 来作为头文件的保护措施,编译器并不会智能地知道它们实际上是同一个文件,因此会导致重定义错误。

然而,我不确定这是否是你的问题,因为它取决于:

  • 你从虚拟磁盘和物理磁盘都进行了包含
  • 你的头文件保护措施是 #pragma once,而不是宏定义的保护措施

.


0
将您的函数放在一个匿名命名空间中。这将消除重复函数定义错误。例如:
 namespace {
     function goes here
  }

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