Есть ли какой-либо реальный вариант использования для спецификаторов функций?

Недавно я узнал о function reference qualifiers, например.

struct foo
{
    void bar() {}
    void bar1() & {}
    void bar2() && {}
};

Где мне может понадобиться эта функция, существует ли какой-либо реальный прецедент для этой языковой функции?

Ответы

Ответ 1

В основном два использования:

  • Чтобы обеспечить оптимизированную перегрузку, например, чтобы перемещать элемент из временного объекта, а не копировать его.
  • Предотвращение неправильного использования API. Например, никто не ожидал бы

    int a = 1 += 2;
    

    и это также вызовет ошибку компиляции. Однако

    string b = string("foo") += "bar";
    

    является законным, если operator += объявлен как

    string & operator += (string const & o);
    

    как это обычно бывает. Также у этого есть неприятный побочный эффект предоставления lvalue-reference для вашего rvalue. Плохая идея. Это можно легко предотвратить, объявив оператор как

    string & operator += (string const & o) &;
    

Ответ 2

Где мне может понадобиться эта функция, существует ли какой-либо реальный прецедент для этой языковой функции?

Пример, который вы показываете, довольно бесполезен, он более полезен, когда у вас есть перегруженная функция, одна версия, которая работает с lvalues ​​и одна, которая работает с rvalues.

Рассмотрим тип, немного похожий на std::stringstream, который владеет строкой и возвращает ее по значению. Если объект является rvalue, он может переместить строку вместо копирования.

class StringBuilder
{
public:
  std::string get() const& { return m_str; }
  std::string get() && { return std::move(m_str); }

private:
  std::string m_str;
};

Это означает, что когда вы возвращаете StringBuilder из функции и хотите получить из нее строку, вам не нужна копия:

std::string s = buildString().get();

В более общем плане, учитывая функцию f(const X&), если было бы полезно перегрузить ее с помощью f(X&&), то, учитывая функцию-член X::f(), было бы полезно изменить ее на X::f() const& и перегрузить ее с помощью X::f()&&