通过负面警告摆脱gcc转变

时间:2008-11-06 00:15:15

标签: c++ gcc

我有一些看起来像的代码:

template<unsigned int A, unsigned int B>
int foo() {
  int v = 1;
  const int x = A - B;
  if (x > 0) {
    v = v << x;
  }
  bar(v);
}

gcc会抱怨x对于A,B的某些实例化是否定的;但是,我会检查以确保它是非负面的。最好的方法是什么?我知道我可以将x强制转换为unsigned int,但这会导致警告x大于v的宽度(因为它会将负数转为正数) )。我知道有一种解决方法涉及创建一个新的模板化shift函数,但如果可能的话我想避免这种情况。

3 个答案:

答案 0 :(得分:3)

由于A和B在编译时是已知的,因此您不仅可以摆脱警告,而且还可以摆脱运行时if,而不需要任何强制转换,如下所示:

#include <iostream>
using namespace std;

template< unsigned int A, unsigned int B >
struct my
{
    template< bool P >
    static void shift_if( int & );

    template<>
    static void shift_if< false >( int & ) {}

    template<>
    static void shift_if< true >( int & v ) { v <<= A - B; }

    static void op( int & v ) { shift_if< (A > B) >( v ); }
};

template< unsigned int A, unsigned int B >
int foo()
{
    int v = 1;
    my< A, B >::op( v );
    return v;
}

int main() {
    cout << foo< 1, 3 >() << endl;
    cout << foo< 3, 1 >() << endl;
    cout << foo< 300, 1 >() << endl;
    cout << foo< 25, 31 >() << endl;
    return 0;
}

答案 1 :(得分:2)

为什么不将x设为unsigned char类型并进行转换?当然你不需要移动超过255位?

const unsigned char x = static_cast<unsigned char>(A - B);

或者可能使用遮蔽来确保班次是这样的界限:

const unsigned int x = static_cast<unsigned int>(A - B) & 0x1f; // limit A-B to have a range of (0 - 31)

编辑:

回应这里的评论是一个想法:

template<unsigned int A, unsigned int B>
int foo() {
  int v = 1;
  const int x = A - B;
  if (x > 0) {
    v = v << (static_cast<unsigned int>(x) & 0x1f);
  }
  bar(v);
}

注意:您可以用以下内容替换0x1f:(CHAR_BIT * sizeof(T) - 1)

编辑:在回复最新评论时,此代码不会发出任何警告:g ++ -W -Wall -ansi -pedantic test.cc -o test

#include <iostream>

template<unsigned int A, unsigned int B>
int foo() {
  int v = 1;
  const int x = A - B;
  if (x > 0) {
    v = v << (static_cast<unsigned int>(x) & 0x1f);
  }
  return v;
}

int main() {
    std::cout << foo<1, 3>() << std::endl;
    std::cout << foo<3, 1>() << std::endl;
    std::cout << foo<300, 1>() << std::endl;
    std::cout << foo<25, 31>() << std::endl;
}

答案 2 :(得分:0)

这会有用吗?

const short unsigned int x = A - B;

它切断了比需要切断更多的位,但如果你的A - B值足够小......