2017-07-07 39 views
1
#define FALSE 0 
#define TRUE 1 

#define IDS_MYSTR 123 

void FnVariadic(const long nIDS, ...) 
{ 
    std::cout << "WITHOUT option IDS" << std::endl; 
} 

void FnVariadic(const bool bOption, const long nIDS, ...) 
{ 
    std::cout << "WITH option IDS" << std::endl; 
} 

void FnVariadic(const char *pStr, ...) 
{ 
    std::cout << "WITHOUT option STR" << std::endl; 
} 

void FnVariadic(const bool bOption, const char *pStr, ...) 
{ 
    std::cout << "WITH option STR" << std::endl; 
} 


int main() 
{ 
    FnVariadic(FALSE, IDS_MYSTR, "abc"); 
    //FnVariadic(IDS_MYSTR, FALSE, "abc"); //??? 
    FnVariadic(TRUE, IDS_MYSTR, "abc"); 
    FnVariadic(IDS_MYSTR, TRUE, "abc"); //??? 

    FnVariadic(FALSE, "abc%s", "abc"); 
    //FnVariadic("abc%d%s", FALSE, "abc"); 
    FnVariadic(TRUE, "abc%s", "abc"); 
    //FnVariadic("abc%d%s", TRUE, "abc"); 

    system("pause"); 

    return 0; 
} 

有人可以解釋一下這裏怎麼工作funtion超載解析? 令人驚訝的是,如何使用可變參數解析工作函數重載?

//FnVariadic(IDS_MYSTR, FALSE, "abc"); //??? 
    FnVariadic(IDS_MYSTR, TRUE, "abc"); //??? 

第二個編譯但不是第一個編譯。

(註釋行的意思是不編譯)

我使用VS2017,似乎;

首先3個電話使用void FnVariadic(const bool bOption, const long nIDS, ...)和最後2個呼叫使用void FnVariadic(const bool bOption, const char *pStr, ...)

它也intresting那裏。我期望的是應該調用沒有布爾參數的重載。

+3

您的問題FALSE是#define'd,因爲0等於空指針常量,因此解析在long和const char *重載之間是不明確的。這種情況只存在於字面常量0,這就是爲什麼設計nullptr的原因(但正如你所看到的,問題仍然存在於語言中)。 – Shaggi

+0

爲什麼你需要用宏定義'true'和'false'?這些布爾常量是在語言時代之前建立起來的。 – AndyG

+0

@AndyG我們正在使用mfc/atl。這些代碼已被寫入,沒有布爾真/假。這些定義已被使用。但我想了解超負荷解決。不尋找解決方案。 –

回答

2

在重載分辨率中,省略號是最後的手段,如果有更好的匹配,則函數調用將被解析爲匹配。你的函數調用(非註釋)都包含一個整數字面量作爲第一個參數。而且,由於您的宏,當更換是轉換到bool所有可行的候選人,你有兩個候選人

void FnVariadic(const bool bOption, const long nIDS, ...) 
void FnVariadic(const bool bOption, const char *pStr, ...) 

然後在前三您提供整型常量作爲第二個參數。因此,上述兩者之間的第一次重載被稱爲。在最後2中,您提供了字符串文字(可減少到const char*),因此第二次重載被稱爲上述兩者之間。


至於爲何註釋行不進行編譯

// FnVariadic(IDS_MYSTR, FALSE, "abc"); //??? 

這不會編譯,因爲第二個參數是模糊的,一個0具有特殊的意義不幸的是,它可以解決這兩個一const char*以及作爲const long

// FnVariadic("abc%d%s", FALSE, "abc"); 

同樣爲這一項,FALSE是模糊

// FnVariadic("abc%d%s", TRUE, "abc"); 

這裏轉化爲bool"abc%d%s"和​​到橢圓匹配具有相同的優先級,並且因此它是不明確的。


供您參考,它幾乎總是最好使用對C風格variadics編譯時可變參數模板。

+0

是否可以停用這種隱式的0 - > ptr轉換?我的意思是可以防止0作爲ptr代表?用編譯器選項也許? –

+1

@YusufR.Karagöz號GCC對此有警告,但在許多情況下,語言沒有進行這種轉換就會中斷。如果您對解決方案感興趣,那麼重構代碼非常容易,因此它可以正常工作(例如,使用SFINAE)。 – Shaggi

1

正如@Shaggi已經指出的那樣。按照標準,

在引入nullptr之前,將零(0)用作 空指針的標記。例如:

int* x = 0; // x gets the value nullptr 

無對象與地址0分配,並且0(全零位 圖案)是nullptr最常見的代表。零(0)是一個 int。但是,標準的轉換(§10.5.2.3)允許0使用 作爲指針或指針到成員類型

FnVariadic(IDS_MYSTR, FALSE, "abc"); 
         ^~~~const char * OR const long. This is ambiguous. 

的常數作爲你有兩個

void FnVariadic(const bool bOption, const long nIDS, ...) 
void FnVariadic(const bool bOption, const char *pStr, ...)