2014-02-23 31 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