我有两个文件,test.cpp
和foo.h
。test.cpp:
#include <iostream>
class foo;
foo* fooInstance;
template<typename T> T bar() {
return fooInstance->template barInternal<T>();
}
#include "foo.h"
int main() {
fooInstance = new foo();
std::cout << bar<int>();
return 0;
}
foo.h:
class foo {
public:
template<typename T> T barInternal() {
return T(5);
}
};
此代码在MSVC Windows上编译没有问题,在使用G++的Linux(Manjaro KDE)上编译和运行也没有问题,但是,它抛出了这个恼人的警告。
test.cpp: In function ‘T bar()’:
test.cpp:8:23: warning: invalid use of incomplete type ‘class foo’
8 | return fooInstance->template barInternal<T>();
| ^~
test.cpp:3:7: note: forward declaration of ‘class foo’
3 | class foo;
|
为什么它会在G++上抛出一个警告,我如何才能摆脱这个警告(要么改变代码,要么以某种方式禁用这个警告,因为它看起来毫无用处)
1条答案
按热度按时间mw3dktmi1#
这个警告似乎没有相应的警告标志,所以在GCC中禁用它的唯一方法是使用
-w
标志,它无条件地禁用所有警告,并且不能被-Wxxxx
标志覆盖。这个警告没有相应的警告标志的原因(我假设)是因为它实际上诊断了一个病态的情况:您的代码违反了标准。顺便说一句,这也是为什么Clang断然拒绝编译它的原因。
这里的相关规则是[temp.res.general]/6.4:
[...]如果出现以下情况,则程序是病态的,不需要诊断:[...]紧接着其定义的模板的假设示例化将是病态的,因为构造不依赖于模板参数[...]
在这种情况下,紧跟着
bar
定义的bar
的假设示例化将是病态的,因为此时foo
仍然不完整。即使您只打算在foo
完成时示例化模板,根据标准,事实仍然是代码的格式不正确(不需要诊断)。这可以通过向
bar
添加一个额外的模板参数来解决,该参数将默认为fooInstance
:现在,
p
是否指向不完整的类型取决于特定的p
,因此不再满足“由于不依赖于模板参数的构造”的条件。您仍然可以像当前一样调用
bar<int>()
;由于默认模板参数,它意味着bar<int, fooInstance>()
。