[英]Ambiguous Call of “long unsigned int” for “uint32_t”
对于所有[u]int{8|16|32|64}_t
类型,我都有很多函数重载:
std::string f( uint8_t) { /*something*/ }
std::string f( int8_t) { /*something*/ }
std::string f(uint16_t) { /*something*/ }
std::string f( int16_t) { /*something*/ }
std::string f(uint32_t) { /*something*/ }
std::string f( int32_t) { /*something*/ }
std::string f(uint64_t) { /*something*/ }
std::string f( int64_t) { /*something*/ }
//A few more overloads with a few more types (bool, float, const char*, etc.)
我现在使用long unsigned int
类型的参数调用函数名称:
template <typename type_blah> class Something { public:
//...
std::string call_f(void) const {
return f(*((type_blah*)(internal_variable)));
}
//...
};
这会产生一个错误:
错误:重载的'f(long unsigned int&)'的调用不明确
我想会发生这种情况,因为unsigned int
和uint32_t
是不同的类型。 但是,对于long unsigned int
,我无法再重载该函数,因为这是一个冗余定义。 即:
std::string f(long unsigned int) { /*something*/ }
。 。 。 产生:
错误:先前在此处定义的“ std :: string f(uint32_t)”
看来类型机制正在互相作用:由于每次转换都同样有效,它无法弄清楚要使用哪个转换,但是由于已经定义了无转换重载,因此无法定义。
由于种种原因,我无法提出论点。 有没有解决的办法?
平台是在Windows 7 x86-64上运行的g ++ MinGW x86。
您正在使用什么平台?
在Windows(Visual Studio 2010)上, unsigned long int
是与您提到的其他类型不同的类型。
专门为此类型添加重载即可解决该错误。 这个答案(和/或Google)可能会更清楚地说明此问题: unsigned long的类型与Windows(VS2010)上的uint32_t和uint64_t不同 。
我为unsigned long int
定义了一个重载,如下所示:
std::string f( unsigned long int val )
{
// Check that we chose the correct corresponding type
// (This may vary by platform!)
assert( sizeof( unsigned long int ) == sizeof( uint32_t ) );
return f( static_cast<uint32_t>( val ) );
}
...在Visual Studio 2010中进行了如下测试:
void main()
{
std::cout << "sizeof( unsigned long int ): " << sizeof( unsigned long int ) << std::endl;
std::cout << "sizeof( uint32_t ): " << sizeof( uint32_t ) << std::endl;
unsigned long int x = 1u;
std::cout << f( x ) << std::endl;
}
...并获得了预期的结果:
sizeof( unsigned long int ): 4
sizeof( uint32_t ): 4
uint32_t
以下是基于上面提供的代码的“测试”:
#include <string>
#include <cstdint>
#include <iostream>
std::string f( uint8_t) { return "ui8";}
std::string f( int8_t) { return "i8";}
std::string f(uint16_t) { return "ui16";}
std::string f( int16_t) { return "i16";}
std::string f(uint32_t) { return "ui32";}
std::string f(unsigned long long int) { return "unsigned long long";}
std::string f(unsigned long int) { return "unsigned long";}
std::string f( int32_t) { return "i32";}
//std::string f(uint64_t) { return "ui64";}
std::string f( int64_t) { return "i64";}
int main()
{
unsigned long x = 42;
unsigned y = 17;
uint32_t z = 9;
uint64_t w = 135;
std::cout << "x: "<< f(x) << " y: " << f(y) << " z: " << f(z) << " w: " << f(w) << std::endl;
}
样本输出:
$ clang++ ambig.cpp -std=c++0x -Wall -m64
$ ./a.out
x: unsigned long y: ui32 z: ui32 w: unsigned long
$ clang++ ambig.cpp -std=c++0x -Wall -m32
$ ./a.out
x: unsigned long y: ui32 z: ui32 w: unsigned long long
(我用clang ++复制了运行,但g ++的结果相同)
这样可以确保同时覆盖unsigned long
和unsigned long long
类型。 不幸的是,其中之一是uint64_t
,因此必须将其删除。
如果确实将变量声明为unsigned long
,则必须提供一个准确地接受该变量的函数-并且依赖于它等同于uint32_t
可能是不正确的-即使它们的位大小相同。
由于您正在为(几乎?)每种类型定义重载,也许您的函数应该是模板?
template < typename T >
std::string f( T )
{
/*something*/
}
如果有一套适用于所有(甚至大多数)类型的代码,那也可以节省很多工作。
如果由于某种原因您仍然需要强制使用unsigned long int
值的调用将其视为其他类型(例如uint32_t
),则可以在调用站点指定模板实例化:
return f<uint32_t>( *internal_variable );
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.