我觉得这是一个愚蠢的问题,我想答案是一个简单的“否”,尽管除了寻求您的帮助外,我不知道如何确定它。
-Werror
是否会干扰模板的正确性(不确定正确的术语,请参见下面的示例)和/或SFINAE?
考虑这个简单的示例:
template <typename T>
void foo() {
int a;
}
int main() {
//int a; // error: unused variable 'a' [-Werror=unused-variable]
}
用main
编译时,取消注释-Werror
中的行会导致错误。我知道编译器应该为任何模板参数错误的模板生成错误,即使未实例化也是如此。这里不是这种情况。实例化模板时,我只会在这里看到错误(当然实际上只是警告)。
为什么要问这个问题:我总是习惯用-Werror
进行编译,因此我对什么是警告和什么是错误的理解在某些方面有些模糊。现在,对于模板,尤其是SFINAE,如果只是警告或错误,确实会产生很大的不同。
答案 0 :(得分:2)
我知道编译器应该为模板生成错误,这些模板即使未实例化也对任何模板参数都是错误的。
但事实并非如此。如果无法为模板生成实例化,则程序格式错误,不需要诊断 (1)。因此,无论您遇到错误还是“成功”编译,该程序的格式都是错误的。
从另一个角度看,编译器一定不能允许由警告变为错误的错误影响SFINAE,因为这可能会更改有效程序的语义,从而使编译器不合格。因此,如果编译器希望将警告诊断为错误,则必须通过停止编译而不是引入替换失败来做到这一点。
换句话说,Select value
可以使编译器拒绝格式正确的程序(毕竟这是其预期的目的),但是如果更改了一个程序的语义,那将是编译器错误。
(1)引用C ++ 17(N4659),[temp.res] 17.6 / 8:
程序是 格式错误,无需诊断,如果:
- 无法为模板生成有效的专业化...并且该模板未实例化,或者
- ...
答案 1 :(得分:1)
尽管这在很大程度上是实现质量的问题,但是-Werror
确实可以(并且确实)干扰SFINAE。这是一个更复杂的示例进行测试:
#include <type_traits>
template <typename T>
constexpr bool foo() {
if (false) {
T a;
}
return false;
}
template<typename T, typename = void> struct Check {};
template<typename T> struct Check<T, std::enable_if_t<foo<T>()>> {};
int main() {
Check<int> c;
}
行T a;
可以触发该警告(和错误),即使分支已死(它是故意死掉的),因此foo
基本上是constexpr函数,而与T
无关)。现在,根据标准本身,这是一个格式正确的程序。
但是由于Clang和GCC在此处引起错误,并且该错误是在Check
专业化的非直接上下文中,所以我们得到了一个硬错误。即使根据标准本身,由于仅在即时上下文中发生替换失败,它也应该退回到主要模板。