如何实现通用min?

Rya*_*Liu 4 c++ templates

当我写作

T min(T& a,T& b)
{return a<b?a:b;}
Run Code Online (Sandbox Code Playgroud)

并且调用min(3,4),它将产生错误.

如何实现通用min?

And*_*owl 12

那是因为非const左值引用(T&)不能绑定到右值(3并且4是右值,这直观地意味着它们没有对象标识).

尝试使用左值引用const,它可以绑定到rvalues(毕竟,该min()函数不应该改变其参数的状态).

此外,template<typename T>如果您正在编写功能模板,请不要忘记该部分:

template<typename T> // <== Don't forget this, if you are writing a template
T min(T const& a, T const& b)
//      ^^^^^       ^^^^^
{
    return (a < b) ? a : b;
}
Run Code Online (Sandbox Code Playgroud)

例如,考虑这个小程序:

#include <iostream>

template<typename T> // <== Don't forget this, if you are writing a template
T min(T const& a, T const& b)
//      ^^^^^       ^^^^^
{
    return (a < b) ? a : b;
}

int main()
{
    int x = 42;
    int y = 1729;

    std::cout << min(x, y) << std::endl; // Passing lvalues, that would be OK also
                                         // with your original code.

    std::cout << min(42, 1729) << std::endl; // Passing rvalues, this would not be OK
                                             // with your original code (non-const
                                             // lvalue references cannot bind to rvalues)
}
Run Code Online (Sandbox Code Playgroud)

这是一个实例.


更新:

上述解决方案只允许合格值相同类型的min(),否则编译器将无法执行类型推演(如果第一个和第二个参数有不同的类型,应该是什么T呢?):

min(3.14, 42); // Huh? What is `T` here, `double` or `int`?
Run Code Online (Sandbox Code Playgroud)

要强制编译器使用特定类型T,可以显式指定模板参数:

min<double>(3.14, 42);
Run Code Online (Sandbox Code Playgroud)

但是,这不是一个非常优雅的选择(用户每次都必须手动键入正确的模板参数).相反,您可以让您的函数模板接受两个模板类型参数而不是一个:

#include <type_traits>

template<typename T, typename U>
typename std::common_type<T, U>::type min(T const& a, U const& b)
{
    return (a < b) ? a : b;
}
Run Code Online (Sandbox Code Playgroud)

并使用std::common_type<>类型特征(自C++ 11以来可用)来确定要用作返回类型的正确类型.

再一次,这是一个实例.