2012-09-16 19 views
2

我有一个函数声明为:C++如何检查一个函数是否正在接收一个unsigned int?

void foo(unsigned int x) 

我如何检查了foo()不接受负数? 我想,如果我调用foo(-1)抛出一个异常, 当然,因为x被自动转换为无符号,我无法检查其积极性,如:

if not(x>=0){ do_something();}; 

或类似检查。

+0

为什么不直接让它变成'int'? – nneonneo

+0

如果'foo'通过一个隐式转换的'int',比较以确保x <= std :: numeric_limits :: max()' – oldrinb

+0

但是如果我传递的正是最大数? – lucacerone

回答

2

是不是真的做任何好办法,但你可以用一些技巧,做到这一点:

1)声明一个未定义的更好的匹配:

void foo(unsigned int x) { 
    //do something 
} 

void foo(int x); 

2)使用的typeid确定类型。

+2

我喜欢#2的要点,并且使用C++ 11更好公用事业。我确定[this](http://liveworkspace.org/code/5d72d4ed342ba48c82076217f51efffe)并不完美,但它确实给出了可能性的要点。 – chris

+0

@chris我也喜欢。另外,还有'std :: is_unsigned',它可以用来保持特定类型的整数(short和long等)的灵活性。 – jogojapan

+0

至于你能扩展点2吗? @jogojapan所以在标准库中有这样的功能? – lucacerone

2

您定义了该函数,因此需要参数unsigned int,因此它不可能接收到负值。

如果用int参数调用它,该值将从int隐含转换为unsigned int,并且该转换的结果已定义良好。这是该语言的一个特性,除非编译器碰巧给你提供了一种方法,否则你不能关闭它 - 而且我不知道这样做的编译器。

至于你的功能而言,这两个调用:

foo(-1);  /* -1 is converted to unsigned int, to the value UINT_MAX */ 
foo(UINT_MAX); 

是无法区分的。这不是唯一的情况; 任何负数int值将被转换为有效的unsigned值。

如果非常大的值被认为对foo()无效,那么您可以检查参数值是否在某个“合理”范围内 - 但是定义什么是“合理”并不总是那么容易。

+0

我不认为这解决了这个问题,问题不在于foo是否可以处理'INT_MAX'和'UINT_MAX'之间的数字,问题是如何在传递类型为int的参数而不是unsigned int时获得编译器错误。 – wich

0

我不是一个C++专家,但是...

你只需要固定数量的比特(通常为32或64)来表示的整数。如果你知道你永远不会有一个小于零的整数,你可以使用所有这些位并存储一个更大的数字。如果您的编号可能小于零,则编译器必须为该符号预留一点位。

它比这更复杂 - 请参阅Wikipedia article on 2's complement。长话短说,在foo内部,如果你看到x是“真的很大”,那么你可能已经通过了一个负数。

检查您的编译器文档是否为int vs uint的大小。

您可能会想要将参数更改为普通整数void foo(int x),或者只是放松一下,知道您当前的设置x不会小于零。

1

正如其答案所示,您可以添加foo的重载版本,该版本需要int参数。既然你说你想foo(-1)抛出异常,你可以有超载foo()做到这一点:

#include <iostream> 

class Wrong_Type { 
public: 
    Wrong_Type(){} 
}; 

void foo(unsigned n) { 
    std::cout << "In foo, unsigned n = " << n << "\n"; 
} 

void foo(int n) { 
    std::cout << "In foo, int n = " << n << "\n"; 
    throw Wrong_Type(); 
} 

int main() { 
    try { 
     foo(-1); 
    } 
    catch (Wrong_Type) { 
     std::cout << "Caught Wrong_Type exception\n"; 
    } 
} 

当我运行此,输出是:

In foo, int n = -1 
Caught Wrong_Type exception 

但是,这不是一个理想的解决方案,因为它会抛出基于参数类型的异常,而不是其值。 1-1都是int类型,所以调用foo(1)也会引发异常。而一些其他有效的呼叫,例如foo(1.0),则变得模糊不清。

如果您可以用foo(1U)替换foo(1),其中1Uunsigned int类型的常量,那么这可以工作。

相关问题