Sta*_*nny 56 c++ algorithm stl reference c++17
std::tie(a, b) = std::minmax(a, b);
Run Code Online (Sandbox Code Playgroud)
我认为这是直观的代码。干净易懂。太糟糕了,它作为的std::minmax模板无法正常工作const&。因此,如果在内部交换值,则std::pair<const&, const&>一个分配将覆盖另一个值:
auto[a, b] = std::make_pair(7, 5);
std::tie(a, b) = std::minmax(a, b);
std::cout << "a: " << a << ", b: " << b << '\n';
Run Code Online (Sandbox Code Playgroud)
a:5,b:5
此处的预期输出为a: 5, b: 7。
我认为这很重要,因为实现转换功能以将功能应用于某些范围需要直观的lambda声明。例如:
std::vector<int> v{ 0, 1, 0, 2, 0 };
std::vector<int> u{ 1, 0, 1, 0, 1 };
perform(v.begin(), v.end(), u.begin(), [](auto& a, auto& b){
std::tie(a, b) = std::minmax(a, b);
});
//v would be == {0, 0, 0, 0, 0}
//u would be == {1, 1, 1, 2, 1}
Run Code Online (Sandbox Code Playgroud)
我发现的一个解决方案是在上构造一个std::tuple没有任何引用限定符的显式结构,std::pair<const&, const&>以强制执行副本:
std::tie(a, b) = std::tuple<int, int>(std::minmax(a, b));
Run Code Online (Sandbox Code Playgroud)
但是这种<int, int>冗余似乎很糟糕,尤其是在auto& a, auto& b之前已经说过的时候。
有没有一种不错的,简短的方法来执行此分配?难道这是一个错误的方向,只是说if (a >= b) { std::swap(a, b); }这是最好的方法?
Ted*_*gmo 58
您可以将初始化列表用于minmax:
std::tie(a, b) = std::minmax({a, b});
Run Code Online (Sandbox Code Playgroud)
就像使用一元加号时一样,这将导致创建临时对象,但它的好处是它也可用于缺少一元加号运算符的类型。
using namespace std::string_view_literals;
auto [a, b] = std::make_pair("foo"sv, "bar"sv);
std::tie(a, b) = std::minmax({a, b});
std::cout << "a: " << a << ", b: " << b << '\n';
Run Code Online (Sandbox Code Playgroud)
输出:
a: bar, b: foo
Run Code Online (Sandbox Code Playgroud)
难道这是一个错误的方向,只是说
if (a >= b) { std::swap(a, b); }这是最好的方法?
我if(b < a) std::swap(a, b);之所以会这样做是因为“ 比较1”的要求,但是,是的,我怀疑这样做会更快,并且仍然很清楚您想要完成什么。
[1] Compare [...]应用于比较类型的对象的函数调用操作的返回值,在上下文中转换为bool时,如果在严格弱函数中调用的第一个参数出现在第二个参数之前,则返回true由这种类型引起的排序关系,否则为false。
lub*_*bgr 25
您可以按照一定的简短程度执行此操作,如下所示。
std::tie(a, b) = std::minmax(+a, +b);
std::cout << "a: " << a << ", b: " << b << '\n';
Run Code Online (Sandbox Code Playgroud)
说明:内置的一元加运算符,为了与其一元减同级符号对称起见,按值返回其操作数(它也执行通常的算术转换,但不适用于ints)。这意味着它必须创建一个临时文件,即使该临时文件不过是操作数的副本。但是对于minmax本例中的用法来说,这已经足够了:这里不再交换引用,因为右侧的引用(const int&传递给的参数minmax)与左侧的对象引用的对象不同。侧面(在所tuple创建的引用的里面std::tie)。
输出是所需的:
a:5,b:7
有时,退后一步并找到不同的方法是有回报的:
if (b < a)
std::iter_swap(&a, &b);
Run Code Online (Sandbox Code Playgroud)
这很简洁,而且通常更有效,当然至少是同等的。也许把它打包成自己的函数:
template <class T>
void reorder(T& a, T& b)
noexcept(noexcept(b < a, void(), std::iter_swap(&a, &b))) {
if (b < a)
std::iter_swap(&a, &b);
}
Run Code Online (Sandbox Code Playgroud)
我正在使用,std::iter_swap()所以我不必using std::swap; swap(a, b)在 C++2a 之前的通用性中使用两步,它引入了定制点对象,使其过时。