我有一些看起来像的代码:
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
函数,但如果可能的话我想避免这种情况。
答案 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值足够小......