没有使用模板函数从“int”自动转换为“float”

No Automatic Cast from `int` to `float` with Template Function

经过多年的 C++ 编码,今天我被问到一个简单的问题,但确实找不到答案,所以我来了。

除了想知道为什么这个错误发生,我想知道如何我可以通过修改 [=16] 来解决下面的错误=]模板函数(不改变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;
}

就这样:

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

与unique T一样,推导一次为int,推导一次为double...

I want to know how I can solve below error by modifying just the template function

像那样:

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

当你有

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

firstsecond的类型必须相同。如果你想采用两种不同的类型,那么你可以添加第二个模板参数

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

或 C++11

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

Besides wondering why this error is happening,

调用Add(1.f, 2)时,第一个参数类型为float,第二个参数类型为int.

编译器必须将第一个参数转换为 int 或将第二个参数转换为 float。由于他们都需要转换,因此他们同样是不错的候选人。一个不能优于另一个。

I want to know how I can solve below error by modifying just the template function

您可以将功能模板更改为:

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.

编译器正在尝试推断可用于创建与签名匹配的函数的模板类型。由于参数是不同的类型,所以无法这样做。

您可以明确指定类型:

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

但现在您必须假设要使用哪种类型 return。

我从未尝试使用 auto 作为 return 类型,但显然它有效:http://ideone.com/1qO95w

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

为什么标准已经提供了自己的函数?

在c++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;
}

在 c++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;
}