使用std :: array进行div-by-zero的gcc警告

时间:2016-03-11 22:54:15

标签: gcc

说:

int main()
{
    int nX = 1 % 0; // <-- warning: divisioin by zero [-Wdiv-by-zero]
}

template<int N> struct A
{
    std::array<int, N> m_Data;

    int &Next()
    {
        return m_Data[(1 + 0) % N];   // <-- no warnings for N == 0
    }
};

int main()
{
    A<0> a; // nothing happens
}

为什么gcc不会发出任何警告,即使我使用``-Wall&#34; ?谢谢大家!

1 个答案:

答案 0 :(得分:0)

  

为什么即使我使用&#34; -Wall&#34; gcc也不会提出任何警告。 ?

仅仅因为gcc的行为(或者更确切地说,g ++; g ++ 5.2 in 我的情况)在这方面是不一致的。它似乎忘记了 模板实例化上下文中的除零诊断。在以下程序中:

int foo(int i) {
    return i % 0;
}

template<typename T>
T bar(T i) {
    return i % 0;
}


#include <iostream>

int main()
{
    std::cout << foo(1) << std::endl;
    std::cout << bar(1) << std::endl;
    return 0;
}

由...引起的函数模板bar<T>的实例化 call bar(1)是一个与foo相同的函数。但是:

$ g++-5 -c -std=c++11 -Wall -pedantic -Wextra main.cpp
main.cpp: In function ‘int foo(int)’:
main.cpp:2:14: warning: division by zero [-Wdiv-by-zero]
     return i % 0;
              ^

g ++诊断仅在foo中除以零,而:

$ clang++-3.7 -c -std=c++11 -Wall -pedantic -Wextra main.cpp
main.cpp:2:14: warning: remainder by zero is undefined [-Wdivision-by-zero]
    return i % 0;
             ^ ~
main.cpp:7:14: warning: remainder by zero is undefined [-Wdivision-by-zero]
    return i % 0;
             ^ ~
main.cpp:16:18: note: in instantiation of function template specialization
      'bar<int>' requested here
    std::cout << bar(1) << std::endl;

clang ++诊断foobar<int>中的除以零。

同样在该计划中:

#include <array>

template<int N> struct A
{
    std::array<int, N> m_Data;

    int &Next()
    {
        return m_Data[(1 + 0) % N];
    }
};

struct B
{
    std::array<int, 0> m_Data;

    int &Next()
    {
        return m_Data[(1 + 0) % 0];
    }
};

#include <iostream>

int main()
{
    A<0> a;
    std::cout << a.Next() << std::endl;
    B b;
    std::cout << b.Next() << std::endl;
    return 0;
}

B与类A<0>相同,但仅限g ++诊断:

main.cpp: In member function ‘int& B::Next()’:
main.cpp:32:31: warning: division by zero [-Wdiv-by-zero]
         return m_Data[(1 + 0) % 0];
                               ^

而clang ++诊断:

main.cpp:32:31: warning: remainder by zero is undefined [-Wdivision-by-zero]
        return m_Data[(1 + 0) % 0];
                              ^ ~
main.cpp:22:31: warning: remainder by zero is undefined [-Wdivision-by-zero]
        return m_Data[(1 + 0) % N];
                              ^ ~
main.cpp:43:20: note: in instantiation of member function 'A<0>::Next' requested here
    std::cout << a.Next() << std::endl;
                   ^

当然,不需要符合标准的编译器来诊断除零, 即使它可以。如果它能够这样做的话,它只会有所帮助。

如果它有时会这样做,而且有时无法做到,那就没有用了。然而, 正如您可能已经知道的那样,编译时完整性检查了属性 模板参数可以用语言和库的功能来实现 如static_assertstd::enable_ifSFINAE。您的 示例模板可能需要N!= 0喜欢:

template<int N> struct A
{
    static_assert(N != 0,"N cannnot be 0 in struct A<N>");
    std::array<int, N> m_Data;

    int &Next()
    {
        return m_Data[(1 + 0) % N];
    }
};