"Вы не можете перенаправлять классы объявлений, которые перегружают оператора &"?

В Руководстве по стилю Google С++ есть раздел Перегрузка операторов, в котором есть любопытное утверждение:

Перегрузка также вызывает удивление последствия. Например, вы не можете forward объявляет классы, которые перегружают operator&.

Это кажется неправильным, и я не смог найти код, который вызывает у GCC проблемы с ним. Кто-нибудь знает, к чему относится этот оператор?

Ответ 1

5.3.1 Стандарта имеет "Адрес объекта неполного типа, который может быть принят, но если полный тип этого объекта является типом класса, который объявляет оператор &() как функцию-член, то поведение undefined (и диагностика не требуется).

Я тоже этого не знал, но, как отметил другой плакат, легко понять, как это может заставить компилятор генерировать неверный код.

Ответ 2

Я тоже не слышал об этом, но это дает потенциально запутывающие результаты для одного и того же кода до и после перегрузки:

#include <iostream>

class Foo;

void bar (Foo& foo) {
    std::cout << &foo << std::endl;
}

class Foo {
public:
    bool operator & () { return true; }
};

void baz (Foo& foo) {
    std::cout << &foo << std::endl;
}

int main () {
    Foo foo;

    bar(foo);
    baz(foo);

    return 0;
}

выход:

0x7fff092c55df
1

Хотя есть и другие причины, по которым вы этого не сделаете - перегрузка адреса не играет хорошо с stl или много общего кода.

Ответ 3

Я думаю, что это утверждение неточно. Как и другие ответы, я предполагаю здесь. Во-первых, я предполагаю, что они относятся к унарный оператор & а не бинарный оператор &. То есть:

int x = 5;
int* p = &x; // unary &
if (x & 1)   // binary &

Вы можете переслать объявление любого класса, который вы хотите. Однако, если класс перегружает унарный оператор &, и вы вызываете унарный оператор & на указателе на один из этих объектов вы, вероятно, получите непоследовательное поведение (иногда вы просто получите адрес, а иногда вы вызовете перегруженный метод). Это может легко превратиться во что-то почти невозможное для отладки.


Я рад, что физцер действительно посмотрел на стандарт и не просто догадался.

Ответ 4

Из-за возможности перегрузить оператор & библиотека ускорения предлагает удобный шаблон addressof(), чтобы позаботиться о поиске реального адреса класса. Не то чтобы я предлагаю вам перегружать оператора &, но если вам нужно, доступна помощь.

Ответ 5

Отредактировано для учета комментариев:

Это предположение, но одна из основных причин, по которым нужно переслать объявление, - это возможность указывать указатели на этот класс. Компилятор должен сделать предположения о классе перед определением - например, размером указателей.

Можно ли изменить размер T * при перегрузке оператора & для Т? (EDIT: комментарии - и я думаю, что нет) - но

Какое предположение нарушено при перегрузке оператора & - Как он меняет класс?

Вот один из способов.

Я мог бы написать:

class A;

void f(A& x) {
    A* xPointer = &x;
}

Это имеет новое значение, если оператор &() перегружен, чем если нет, и компилятор может подумать, что он может генерировать код для него, но это было бы неправильно.

Ответ 6

Неясно формулировка, вы можете, конечно, объявить класс, но правило, очевидно, занимает позицию, которую вы "не должны", когда класс перегружает operator&.

Подобные правила также присутствуют в других стандартах кодирования, например JSF (pdf) правило 159 гласит, что operator& не должно быть перегружено.