使用英特尔编译器icpc13时,以下代码给出了警告。
#include <iostream>
template<int N>
class base
{
public:
double x[N];
};
template<int N>
class derived : public base<2*N>
{
public:
void print()
{
if (N==1)
{
std::cout << this->x[1] << std::endl;
}
else if (N==2)
{
std::cout << this->x[3] << std::endl;
}
}
};
int main(int argc, char* argv[])
{
derived<1> temp1;
derived<2> temp2;
temp1.print();
temp2.print();
}
结果:%icpc-13.1.163 main.cpp main.cpp(29):警告#175:
下标超出范围std :: cout&lt; x [3]&lt;
在“void derived :: print()[有N = 1]”的实例化过程中 41
这显然不是危险,因为if语句在模板参数为1时保护这行代码。
我知道我“应该”为这些事情做模板专业化,但真实函数中有一些共享代码使得模板参数上的if语句非常方便。
问题是......这是一个“坏”的事情,或者这是不正确的编译器行为?我没有收到gcc或xlc的警告。
我选择了pragma解决方案。最终看起来像这样:
void print()
{
#ifdef __INTEL_COMPILER
#pragma warning push
#pragma warning disable 175
#endif
if (N==1)
{
std::cout<<this->x[1]<<std::endl;
}
else if (N==2)
{
std::cout << this->x[3] << std::endl;
}
#ifdef __INTEL_COMPILER
#pragma warning pop
#endif
}
};
据我所知,push会在禁用之前保存警告标志,pop会恢复它们。
答案 0 :(得分:1)
编译器会检查代码分支,即使它们因编译时常量而处于非活动状态。
ICPC似乎是唯一检查数组边界的,但你可能会遇到其他令人讨厌的警告,例如Visual C ++,它会在检查N时警告常量条件表达式(C4127警告级别为4)。
我绝对会照顾警告,你的里程可能会有所不同:
-wd175
#pragma warning(disable: 175)
derived<>::print()
方法并将公共代码分解出来:template<>
void derived<1>::print()
{
std::cout << x[1] << std::endl;
call_common();
}
template<>
void derived<2>::print()
{
std::cout << x[3] << std::endl;
call_common();
}
derived<>::print_x()
:template<>
void derived<1>::print_x()
{
std::cout << x[1] << std::endl;
}
template<>
void derived<2>::print_x()
{
std::cout << x[3] << std::endl;
}
template<int N>
void derived<N>::print()
{
print_x();
// ...
}