我有一堆针对所有[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::字符串 f(uint32_t)"之前在此处定义
似乎类型机制是相互对抗的:它无法确定使用哪个转换,因为每个转换都同样有效,但无法定义无转换重载,因为它已经有效。
由于各种原因,我无法提出论点。 有没有办法摆脱这种情况?
平台是运行在Windows 7 x86-64上的g ++ MinGW x86。
您使用什么平台?
在Windows(Visual Studio 2010)上,unsigned long int
与您提到的其他类型不同。
专门为该类型添加重载解决了错误。 这个答案(和/或谷歌)可能会更清楚地说明这个问题:未签名长整型的类型与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 );