Нет Автоматическое преобразование из `int` в` float` с функцией шаблона

После нескольких лет кодирования в С++ сегодня мне задали простой вопрос, но я действительно не смог найти его ответ, и поэтому я ребята.

Кроме того, интересно, что почему эта ошибка происходит, я хочу знать , как, я могу решить ниже ошибку, изменив только функцию шаблона (без изменение функции main())

template <class T>
T Add(T first, T second)
{
    return first + second;
}

int main()
{
    auto sample_1 = Add(1, 2); // Works
    auto sample_2 = Add(1.f, 2.f); // Works
    auto sample_3 = Add(1.f, 2); // Error: no instance matches the argument types: (double, int)
    return 0;
}

Ответ 1

Кроме того, интересно узнать, почему эта ошибка происходит,

Когда вы вызываете Add(1.f, 2), первый тип аргумента - float, а второй тип аргумента - int.

Компилятор должен преобразовать либо первый аргумент в int, либо второй аргумент в float. Поскольку для обоих из них потребуется преобразование, они одинаково хороши. Нельзя быть предпочтительнее другого.

Я хочу знать, как я могу решить ниже ошибку, изменяя только функцию шаблона

Вы можете изменить шаблон функции:

template <class T1, class T2>
auto Add(T1 first, T2 second)
{
    return first + second;
}

или (спасибо @PiotrSkotnicki):

template <class T>
T Add(T first, decltype(first) second)
{
    return first + second;
}

В этом случае тип second не выводится из аргумента, передаваемого функции. Тип first выводится из первого аргумента, а тип second вынужден быть таким же, как тип first.

Add(1.2f, 2);  // The first argument is deduced to be float
               // The second argument is forced to be float.

Add(2, 1.2f);  // The first argument is deduced to be int
               // The second argument is forced to be int.

Ответ 2

Просто выполните:

template <class T1, class T2>
auto Add(T1 first, T2 second)
{
    return first + second;
}

Как и в случае с уникальным T, он выводится один раз как int, один раз как double...

Ответ 3

Если у вас

template <class T>
T Add(T first, T second)

тип first и second должен быть одинаковым. Если вы хотите использовать два разных типа, вы можете добавить второй параметр шаблона

template <class T1, class T2>
auto Add(T1 first, T2 second)

или для С++ 11

template <class T1, class T2>
auto Add(T1 first, T2 second) -> decltype(first + second)

Ответ 4

Компилятор пытается вывести тип шаблона, который он может использовать для создания функции, соответствующей сигнатуре. Поскольку параметры являются разными типами, он не может этого сделать.

Вы можете явно указать тип:

auto sample_3 = Add<float>(1.f, 2);

Но вы говорите, что не хотите этого делать.

Вы можете изменить функцию, чтобы взять два типа шаблонов:

template <class T1, class T2>
T1 Add(T1 first, T2 second)
{
    T1 p;
    p = first + second;
    return p;
}

Но теперь вам нужно будет сделать предположение о том, какой тип будет возвращен.

Я никогда не пытался использовать auto как возвращаемый тип, но, по-видимому, он работает: http://ideone.com/1qO95w

template <class T1, class T2>
auto Add(T1 first, T2 second)
{
    auto p = first + second;
    return p;
}

Ответ 5

Зачем писать свою собственную функцию, когда стандарт уже предоставил их?

В С++ 11 вы можете использовать:

#include <functional>
int main()
{
    auto sample_1 = std::plus<float> () ( 1, 2 ); // Works
    auto sample_2 = std::plus<float> () ( 1.f, 2.f ); // Works
    auto sample_3 = std::plus<float> () ( 1.f, 2 ); // Works
    return 0;
}

В С++ 14:

#include <functional>
int main()
{
    auto sample_1 = std::plus<> () ( 1, 2 ); // Works
    auto sample_2 = std::plus<> () ( 1.f, 2.f ); // Works
    auto sample_3 = std::plus<> () ( 1.f, 2 ); // Works
    return 0;
}

Ответ 6

Я хочу знать, как я могу решить ниже ошибку, изменяя только функцию шаблона

Вроде:

template <class T1, class T2>
T1 Add(T1 first, T2 second)
{
    T1 p;
    p = first + second;
    return p;
}

int main()
{
    auto sample_1 = Add(1, 2);
    auto sample_2 = Add(1.f, 2.f);
    auto sample_3 = Add(1.f, 2);
    return 0;
}