Почему оператор-> может быть перегружен вручную?

Не имеет смысла, если p->m был просто синтаксическим сахаром для (*p).m? По существу, каждый operator->, который я когда-либо писал, мог быть реализован следующим образом:

Foo::Foo* operator->()
{
    return &**this;
}

Есть ли случай, когда я хотел бы, чтобы p->m означал что-то еще, чем (*p).m?

Ответы

Ответ 1

operator->() имеет странное различие , неявно вызываемое повторно, в то время как тип возвращаемого значения позволяет ему. Самый ясный способ показать это с кодом:

struct X {
    int foo;
};

struct Y {
    X x;
    X* operator->() { return &x; }
};

struct Z {
    Y y;
    Y& operator->() { return y; }
};

Z z;
z->foo = 42;          // Works!  Calls both!

Я вспоминаю случай, когда это поведение было необходимо для того, чтобы объект мог вести себя как прокси для другого объекта в контексте с интеллектуальным указателем, хотя я не могу запомнить детали. Я помню, что я мог только заставить поведение работать, как я предполагал использовать синтаксис a->b, используя этот странный частный случай; Я не мог найти способ заставить (*a).b работать аналогичным образом.

Не уверен, что это отвечает на ваш вопрос; я действительно говорю: "Хороший вопрос, но это даже странно!"

Ответ 2

Один пример использования может быть, когда вы создаете DSL внутри С++, в соответствии с Boost Karma (хотя это не кажется перегрузить -> в свою библиотеку), где вы полностью меняете смысл традиционных операторов С++. Является ли это хорошей идеей, безусловно, для обсуждения.

Ответ 3

Регулярные указатели предлагают p->m и (*p).m, причем p->m является наиболее распространенным. Если вы допустили только перегрузку одного из них, это будет несовместимо с типом по умолчанию. Что касается того, почему не позволить компилятору переписать его, простой ответ заключается в том, что иногда вы не хотите, чтобы operator- > возвращал T *, где оператор * возвращает T &. Позволяя им перегружать отдельно, вы можете комбинировать комбинации, о которых вы не можете думать. Но было бы глупо отрицать это, просто потому, что мы не можем сейчас думать о какой-либо причине, чтобы изменить его. Как бы то ни было, у вас мог бы быть класс int128 и оператор перегрузки + = для обозначения возведения в степень вместо этого, если вы этого хотели.

Ответ 4

Возможно, вы захотите выполнить некоторые другие операции, такие как увеличение переменной (подсчет доступа) или даже некоторые проверки безопасности и т.д. С другой стороны, мне никогда не нужно было перегружать оператор- > ...

Ответ 5

Я думаю, что он использовался для shared_ptr < > in boost (например). Это делает их "похожими на обычные указатели", хотя они являются особыми указателями (ссылка на счет afaik).