【问题标题】:How to use GCC diagnostic pragma with C++ template functions?如何将 GCC 诊断编译指示与 C++ 模板函数一起使用?
【发布时间】:2023-04-07 00:45:01
【问题描述】:

我想使用 g++ 和 -Werror,所以我现在必须禁用我无法控制的第 3 方库的警告。 http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html 提供的解决方案效果很好,允许简单地用编译指示包装 3rd 方标头的包含。不幸的是,在涉及模板的特定设置中,这不再适用于我。我创建了以下最小示例,说明这种方法没有按预期工作:

源文件 main.cpp

#pragma GCC diagnostic ignored "-Wunused-parameter"
#include "hdr.hpp"
#pragma GCC diagnostic error "-Wunused-parameter"
int main() {
    return mytemplatefunc(2) + mystandardfunc(3); // will print ONLY ONE warning
}

和头文件 hdr.hpp

template<typename T>
int mytemplatefunc(T t) {
    return 42;
}
int mystandardfunc(int i) {
    return 53;
}

使用 Makefile 编译

CPPFLAGS+=-Wunused-parameter -Werror
main: main.cpp

会产生以下编译错误

g++  -Wunused-parameter -Werror   main.cpp   -o main
In file included from main.cpp:3:
hdr.hpp: In instantiation of ‘int mytemplatefunc(T) [with T = int]’:
main.cpp:29:   instantiated from here
hdr.hpp:2: error: unused parameter ‘t’
make: *** [main] Error 1
shell returned 2

请注意,在包含标头之后直接在 main.cpp 中显式实例化不起作用,并且在 main.cpp 中包装对模板函数的调用也不起作用。令人费解的是,将 #pragma GCC diagnostic ignored "-Wunused-parameter" 放在 main 函数前面会使编译器静音,而在文件的非常末尾添加 #pragma GCC diagnostic error "-Wunused-parameter" 会导致编译器再次产生错误。如何解决这个难题?

(注意,关于这个 pragma 的帖子有几十个,但我找不到任何人 涉及这样的设置)

【问题讨论】:

  • 从提供的链接中,“GCC 跟踪每个 pragma 的位置,并根据源文件中该点的状态发出诊断信息。因此,#pragmas 发生在一行之后不影响由该线路引起的诊断。”因此,即使您只是在代码末尾重新打开错误,如果您仍然遇到问题......您是否尝试过将第二个#pragma 设置为diagnostic warning 而不是diagnostic error?如果它仍然将其报告为错误而不是警告,那么您可能需要检查您的头文件中的#pragmas。
  • 不,那么它将报告为警告。但这不符合我的要求。这样做的整个想法是有错误而不是警告(-Werror),这样我就会收到编译失败的通知,而不是必须手动扫描多页编译器输出(如果我必须区分警告,这将很困难我实际上可以做一些事情,以及我必须忽略的警告)。我认为 hdr.hpp 超出了我的控制范围(想象一下它是第 3 方)。
  • spinics.net/lists/gcchelp/msg30702.html 似乎与这个问题有关。我正在使用 gcc 4.4.5。这似乎不支持在比文件级别更精细的范围内使用这种编译指示。在进一步的测试中,我取消了标头并使用了 -Wuninitialized ,它的行为也很奇怪。

标签: c++ templates gcc pragma diagnostics


【解决方案1】:

问题是模板的实例化是在您使用它时编译的,而不是在编译器在头文件中解析它时,因此它不会发出警告,直到它将 T 替换为 int 并将其解析为常规在 pragma silencing 的上下文之外起作用。

【讨论】:

    【解决方案2】:

    表明您不打算使用参数的常用方法是不给它一个名称:

    template<typename T> 
    int mytemplatefunc(T /* t */) 
    { return 42; } 
    
    int mystandardfunc(int /* i */) 
    { return 53; } 
    

    【讨论】:

    • 是的,这行得通!实际上,我应该在我的描述中包含标题实际上是我无法控制的,因此我无法修复标题并且必须在包含该标题的代码部分中使警告静音。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多