Как функция шаблона работает с несколькими типами имен, которые могут иметь пересечение? - PullRequest
0 голосов
/ 03 февраля 2020

Я новичок в C ++ и в настоящее время пытаюсь понять, как работают функции шаблона. Сначала я хотел добавить два числовых значения одного и того же типа, что довольно легко понять.

template <typename T>
T add(T a, T b){return a+b;}
int main(){
    float a_f=2.5;float b_f=1.5;float c_f;
    int a_i=2;int b_i=1;int c_i;
    c_f = add(a_f, b_f);
    c_i = add(a_i, b_i);
    return 0;
}

Затем я хотел добавить два числовых числа с разными и одинаковыми типами. Мое наивное предположение было таким:

template<typename R, typename S, typename T>
R add(S a, T b){return a+b;}
int main(){
    float a=3.2; int b=2;
    auto result1 = add(a,b);    // error: no matching function for call to ‘add(float&, int&)’
    auto result2 = add(a,a);    // error: no matching function for call to ‘add(float&, float&)’
    auto result3 = add(b,b);    // error: no matching function for call to ‘add(int&, int&)’
    return 0;
}

Я знаю, что этот подход не верен, потому что у typename есть пересечение относительно типов данных, и поэтому само объявление не может быть правильным.

Как может быть реализована простая функция add (), которая добавляет два числовых значения c вместе, независимо от типа?

Ответы [ 3 ]

6 голосов
/ 03 февраля 2020

Проблема не в пересечении, а в том, что оно не может вывести R. В

template<typename R, typename S, typename T>
R add(S a, T b){return a+b;}

Ничто не говорит компилятору, каким должен быть R. Он не выводится из переменной, которой вы присваиваете результат, и вы не указываете его, поэтому нет действительного вызова, который он может сделать. Чтобы это исправить, вы можете просто избавиться от R и использовать тип возврата auto, чтобы он выводился для вас как

template<typename S, typename T>
auto add(S a, T b){return a+b;}
5 голосов
/ 03 февраля 2020

Как можно реализовать простую функцию add(), которая добавляет два значения чисел c независимо от типа?

В C ++ 14:

template<class T, class U>
auto add(T t, U u) {
    return t + u;
}

В приведенном выше примере тип возвращаемого значения выводится из типа выражения t + u.

C ++ 11 не выводит типы возврата, но допускает конечный тип возврата, поэтому Версия C ++ 11:

template<class T, class U>
auto add(T t, U u) -> decltype(t + u) {
    return t + u;
}
2 голосов
/ 03 февраля 2020

То, что вы хотите, это вывести тип возвращаемого значения. Однако вычет типа для параметра шаблона типа применяется только для параметра функции.

Несмотря на то, что имена типов не являются подходящим инструментом для этого, C ++ предлагает другое средство для вывода типа.

Использовать auto

Вы можете просто поместить туда auto и позволить компилятору сделать вывод из типа возвращаемого значения:

template<typename S, typename T>
auto add(S a, T b){ return a + b; }

Использовать конечные типы возврата

Вы также можете использовать конечный тип возврата если вы хотите более точно указать тип возвращаемого значения функции:

template<typename S, typename T>
auto add(S a, T b) -> decltype(a + b) { return a + b; }
...