-Werror是否会干扰模板的正确性和/或SFINAE?

时间:2018-12-06 10:15:08

标签: c++ templates gcc compiler-warnings

我觉得这是一个愚蠢的问题,我想答案是一个简单的“否”,尽管除了寻求您的帮助外,我不知道如何确定它。

-Werror是否会干扰模板的正确性(不确定正确的术语,请参见下面的示例)和/或SFINAE?

考虑这个简单的示例:

template <typename T>
void foo() {
    int a;
}

int main() {
    //int a; // error: unused variable 'a' [-Werror=unused-variable]
}

main编译时,取消注释-Werror中的行会导致错误。我知道编译器应该为任何模板参数错误的模板生成错误,即使未实例化也是如此。这里不是这种情况。实例化模板时,我只会在这里看到错误(当然实际上只是警告)。

为什么要问这个问题:我总是习惯用-Werror进行编译,因此我对什么是警告和什么是错误的理解在某些方面有些模糊。现在,对于模板,尤其是SFINAE,如果只是警告或错误,确实会产生很大的不同。

2 个答案:

答案 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无关)。现在,根据标准本身,这是一个格式正确的程序。

但是由于ClangGCC在此处引起错误,并且该错误是在Check专业化的非直接上下文中,所以我们得到了一个硬错误。即使根据标准本身,由于仅在即时上下文中发生替换失败,它也应该退回到主要模板。