2017-04-20 52 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

相关问题