2008-11-06 67 views
3

我有一些代碼,看起來像:入門負警告擺脫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的某些實例;但是,我確實執行了檢查以確保它不是負面的。最好的解決辦法是什麼?我知道我可以投xunsigned int但這會導致關於x的警告大於v的寬度(因爲它將投射負數爲正數)。我知道有一種解決方法,即創建一個新的模板化功能,但如果可能的話,我想避免這種情況。

回答

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; 
} 
0

這項工作?

const short unsigned int x = A - B; 

它切斷了更多的比特比需要被切斷,但如果你的A值 - B足夠小...

+0

更具體:我有'A == 25 `和`B == 31`。這給了我`x == -6`看起來像`111 ... 11010`並截斷它仍然會給我一個相當大的數字 – 2008-11-06 00:34:21

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測試

#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; 
} 
+0

我相信如果右邊是負數,它會將它轉換爲` unsigned int`,這會使其成爲正數。如果'A-B'的結果是負數,我不想運行代碼。 – 2008-11-06 00:24:49

+0

因爲它知道編譯時的值,所以大於32的任何數字都會標記另一個有關移位大於類型寬度的數字的警告。所以雖然這確實解決了負面問題,但它會提出第二個警告。 – 2008-11-06 00:37:33