关于C ++模板参数的'if'语句

时间:2013-11-24 08:43:47

标签: c++ templates compiler-warnings

使用英特尔编译器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会恢复它们。

1 个答案:

答案 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();
}
  • 将N上的开关分解为自己的专用方法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();
    // ...
}