说:
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; ?谢谢大家!
答案 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 ++诊断foo
和bar<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_assert
,
std::enable_if
和
SFINAE。您的
示例模板可能需要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];
}
};