2014-02-23 30 views
8

我有一大堆的重载所有[u]int{8|16|32|64}_t类型的函数:“长unsigned int类型”为“uint32_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))); 
     } 
     //... 
}; 

这产生一个错误:

error: call of overloaded 'f(long unsigned int&)' is ambiguous


我想这会发生,因为unsigned intuint32_t是不同的类型。但是,我不能为long unsigned int更多地重载函数,因为这是一个冗余定义。 I.e .:

std::string f(long unsigned int) { /*something*/ } 

。 。 。生产:

error: 'std::string f(uint32_t)' previously defined here


看来类机构对彼此的工作:它无法弄清楚要使用的转换,因为每次转换都同样有效,但无转换超载不能因为它已经被定义了。

由于各种原因,我无法施展参数。有没有办法呢?

平台是在Windows 7 x86-64上运行的g ++ MinGW x86。

+2

能你请[SSCCE](http://sscce.org/)向我们展示?或者至少是函数声明和你如何调用它? –

+0

你使用的编译器有32位的“long”吗? –

+2

@MatsPetersson:我不确定这可以解释它。假设OP按照他的说法创建了重载,那么'f(some_unsigned_long)'应该完全匹配至多一个重载。 –

回答

0

以下是我根据上面提供的代码“测试”:

#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 

(我复制了我的铿锵++运行,但结果是得到的相同++)

这确保了无论是unsigned longunsigned long long类型都包括在内。不幸的是,其中之一是uint64_t,所以它必须被删除。

如果你这样做变量声明为unsigned long,你必须提供一个函数,它正是 - 依靠它就等同于uint32_t可能不正确 - 即使他们是相同的bitsize。

+2

“不幸的是,其中一个是'uint64_t',所以它必须被删除。”究竟;但我事先不知道它会是什么。但是,我认为这提供了必要的线索:我只需要处理使用其中一个或另一个。 – imallett

1

你在使用什么平台?

在Windows(Visual Studio 2010)上,unsigned long int与您提到的其他类型不同。

为该类型增加专门的过载解决了错误。这个答案(和/或Google)可能会对此问题提供更多信息:Type of unsigned long is different from uint32_t and uint64_t on Windows (VS2010)

我定义的过载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 
+1

在编辑中增加了平台和一些代码。我看到了那个链接;但它并没有提供*解决方案*。 – imallett

0

既然你正在为(几乎?)每种类型定义重载,也许你的函数应该是一个模板呢?

template < typename T > 
std::string f(T) 
{ 
    /*something*/ 
} 

如果有一组代码,所有的工作 - 甚至是大多数 - 类型,这将节省您大量的工作为好。

如果由于某种原因,你仍然需要强制与unsigned long int值调用把它当作一些其他类型(如uint32_t),你可以在调用点指定模板实例:

return f<uint32_t>(*internal_variable); 
+0

它最初是一个模板,但需要重载,因为某些人可能认为有效的类型不是。如上所述,无论如何我都无法调用特定的实例。 – imallett