简体   繁体   中英

'if' statements on C++ template arguments

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.

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:

  • disable warning with compiler option -wd175
  • disable warning at this specific point with vendor-dependent #pragma warning(disable: 175)
  • specialize the 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();
}
  • factor out the switch on N into its own specialized method 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();
    // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM