2017-04-20 79 views
2

今天在編程語言類的理論,我們在Java中看到這種行爲:不同亞型參數方法

public class Es { 
    ... 
    <Y> Y choose(Y y1, Y y2){ 
     Y returnVal; 
     if("some test"){ returnVal = y1;} else{ returnVal = y2;} 
     return returnVal; 
    } 
} 

在主營:

Es c = new Es(); 
Integer i = 3; 
Float f = (float) 4.5; 
Number n = c.choose(i, f); 

當「不可思議」的是,該方法必須在Integer和Float之間選擇參數類型Y,並選擇最接近的超類型,即Number。

我想重現這在C++,但我堅持......

+2

這些被稱爲[通用方法](https://docs.oracle.com/javase/tutorial/java/generics/methods.html)。我相信你想要在C++模板中進行轉換,但我很久沒有使用過這些了。但是這可以幫助你做一些研究 – AxelH

回答

4

模板在不匹配時不會嘗試調整類型。這就是爲什麼一個簡單實現如下所示:

template <class Y> 
Y choose(Y y1, Y y2) { 
    // ... 
} 

,出現以下錯誤失敗:

main.cpp:8:5: fatal error: no matching function for call to 'choose' 
    choose(1, 2.5f); 
    ^~~~~~ 
main.cpp:3:3: note: candidate template ignored: 
        deduced conflicting types for parameter 'Y' ('int' vs. 'float') 

你想要做的就是讓函數模板採取兩種類型,然後解決的共同點是什麼類型:

template <class Y1, class Y2> 
auto choose(Y1 y1, Y2 y2) { 
    using Y = std::common_type_t<Y1, Y2>; 

    Y returnVal; 

    if("some test") { 
     returnVal = y1; 
    } else { 
     returnVal = y2; 
    } 

    return returnVal; 
} 

一個好主意是使功能SFINAE友好的,也通過提升類型扣除爲其簽名:

template <class Y1, class Y2> 
std::common_type_t<Y1, Y2> choose(Y1 y1, Y2 y2) { 
    // Same as before 
} 
-1

使用模板函數。這做同樣的事情,你的Java代碼的C++代碼實際上是非常類似於Java代碼本身:

template <typename Y> 
Y choose(Y y1, Y y2) { 
    Y returnVal; 
    if("some test"){ returnVal = y1;} else{ returnVal = y2;} 
    return returnVal; 
} 

你可以簡單地把它作爲你的Java編譯器會會推斷出正確的類型:

choose(1,2); //With two ints 
choose("hi","bye"); //With two char*s. 

注:語義,C++模板是從Java泛型很大的不同。 Java泛型使用類型擦除來實現--JRE在運行時不知道類型參數,而C++模板實際上在每次將模板用於不同類型時都創建一個單獨的函數或類。請參閱this answer.

編輯:我誤解了您的問題。不幸的是,我不相信C++有你想要的行爲;您必須明確指定兩者都是超類型。

+0

「該方法必須在參數類型Y的Integer和Float之間進行選擇,並選擇最近的超類型」 - 這裏不做這個。 – Quentin

+0

@Quentin我不認爲在C++中有相當於數字的超類型。 – ostrichofevil

+0

@ostrichofevil不,但是你可以製作一個模板whos默認impl會導致編譯錯誤(如果使用的話),然後專精 – UKMonkey