Why does std :: max return const?

I would like to find max Fooand call inc()on it, which is a non-constant method. Of course, when searching for max, I do not want to create any copies or movements, i.e. I do not want to Foo foo = std::max(foo1, foo2). I tried to write my own max, and g ++ insists returning const &.

#include <iostream>

class Foo
{
public:
  Foo(int x) : x_(x) { std::cout << "const" << std::endl; }
  Foo(const Foo& foo) : x_(foo.x_) { std::cout << "copy const" << std::endl; }
  Foo(Foo&& foo) : x_(foo.x_) { std::cout << "move const" << std::endl; }
  bool operator< (const Foo& foo) const { return x_ < foo.x_; }
  bool operator> (const Foo& foo) const { return x_ > foo.x_; }
  void inc() { ++x_; }
  int x_;
};

/*
 * Doesn't compile.  Must return const T& or must accept non-const T&
 *
template<typename T>
inline T& my_max(const T& f1, const T& f2)
{
  return f1 > f2 ? f1 : f2;
}
*
*/

int main()
{
  Foo foo1(6);      
  Foo foo2(7);      
  Foo& foo = std::max(foo1, foo2); //Doesn't compile.  Must be const Foo&. But then next line fails
  foo.inc();
  std::cout << foo.x_ << std::endl;
  return 0;
}
+4
source share
2 answers

You have 2 questions:

  • Missing const qualifier as a result
  • It is dangerous to return a reference to the const reference parameter

In this case:

Foo& foo = std::max(Foo(6), Foo(7));

- . , , , .

const , , , .

+2
template<typename T>
T my_max(T&& f1, T&& f2) {
  return std::forward<T>(f1 > f2 ? f1 : f2);
}

, . , r/l/const, std::max . max const&.

, , , .

& : . rvalues, .

a super_max, , lvalues ​​ , lvalue. rvalue, :

template<class A, class B>
struct max_return:std::common_type<A,B>{};
template<class A>
struct max_return<A&,A&>{
  using type=A&;
};
template<class A, class B>
using max_return_t = typename max_return<A,B>::type;

template<class T, class U>
max_return_t<T,U> super_max(T&& t, U&& u) {
  if (t < u)
    return std::forward<U>(u);
  else
    return std::forward<T>(t);
}

< .

+2

Source: https://habr.com/ru/post/1570850/


All Articles