Параметрические методы с разными подтипами

сегодня в классе Theory of Programming Language мы видели такое поведение в 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

Решение

Шаблоны не пытаются корректировать типы, когда они не совпадают. Вот почему простая реализация, подобная следующей:

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
}
4

Другие решения

Использовать Функция шаблона. Код C ++, который делает то же самое, что и ваш код Java, на самом деле удивительно похож на сам код 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 ++ фактически создают отдельную функцию или класс каждый раз, когда шаблон используется для другого типа. Увидеть этот ответ

Редактировать: Я неправильно понял ваш вопрос. К сожалению, я не верю, что C ++ ведет себя так, как вы хотите; Вы должны явно указать, что оба являются супертипом.

-1

По вопросам рекламы [email protected]