Я хотел бы найти максимальный Foo
и позвонить по нему inc()
, что является неконстантным методом. Конечно, при поиске max я не хочу создавать какие-либо копии или ходы, то есть я не хочу Foo foo = std::max(foo1, foo2)
. Я попробовал написать свой собственный макс, а g ++ настаивает на возврате константы &.Почему std :: max return by 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;
}
Он возвращает константную ссылку, чтобы избежать ненужного копирования, потому что он еще до ссылки RValue и двигаться семантику. Вероятно, он будет определен по-разному, если его создать сегодня, например. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2199.html –
Другим вариантом было бы добавить 'Foo copy() const & {return * this; } ', поэтому вы можете написать' std :: max (fooA, fooB) .copy(). inc(); '. Иногда это боль, когда у конструктора копирования нет имени. – MSalters
Вы уже знаете один ответ: Ваш комментарий сказал * «... или должен принять неконстантный T & ...» *. Ваши две переменные, 'foo1' и' foo2', не являются константами lvalues, как и переменная, которую вы хотите использовать для хранения max, 'Foo & foo'. Так почему вы вводите 'const' где угодно? Просто оставьте 'const' от вашего' max' - хотя, возможно, вы можете переименовать его 'max_lvalue_ref', чтобы четко указать, что он делает. –