Reputation: 630
The following code gives me a warning when using the Intel compiler 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();
}
Result: % icpc-13.1.163 main.cpp main.cpp(29): warning #175:
subscript out of range std::cout<x[3]<
during instantiation of "void derived::print() [with N=1]" at line 41
This is obviously not a danger since the if statement protects this line of code if the template argument is 1.
I know that I "should" do template specialization for such things, but there is some shared code in the real functions that make the if statements on template arguments really handy.
Question is…is this a "bad" thing to do, or is this incorrect compiler behavior? I don't get warnings with gcc, or xlc.
I chose the pragma solution. This ends up looking like this:
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
}
};
From what I can tell, the push saves the warning flags before the disable, and the pop restores them.
Upvotes: 3
Views: 3154
Reputation: 1359
Compilers do check code branches even they're inactive due to compile-time constants.
ICPC seems to be the only that checks the array bounds, but you could possibly run into other annoying warnings, like from Visual C++, which warns about constant conditional expressions when checking N (C4127 with warning level 4).
I definitely would take care of the warning, your mileage may vary:
-wd175
#pragma warning(disable: 175)
derived<>::print()
method and factor out common code: 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();
// ...
}
Upvotes: 1