Почему «оператор void» не вызывается с синтаксисом приведения? - PullRequest
39 голосов
/ 27 октября 2010

Во время игры с этим ответом от пользователя GMan Я создал следующий фрагмент (скомпилированный с Visual C ++ 9):

 class Class {
 public:
     operator void() {}
 };

 Class object;
 static_cast<void>( object );
 (void)object;
 object.operator void();

после перехода к отладчику я обнаружил, что приведение к void не вызывает Class::operator void(), только третий вызов (с явным вызовом оператора) фактически вызывает оператор, эти два приведения просто ничего не делают.

Почему operator void не вызывается с синтаксисом приведения?

1 Ответ

29 голосов
/ 27 октября 2010

Техническая причина, по которой можно найти в §12.3.2:

Функция преобразования никогда не используется для преобразования (возможно, cv-квалифицированного) объекта в (возможно, cv-квалифицированного) тот же объекттип (или ссылка на него), на (возможно, cv-квалифицированный) базовый класс этого типа (или ссылку на него), или (возможно, cv-квалифицированный) void .

Обоснование (вероятно) состоит в том, чтобы разрешить работу §5.2.9 / 4:

Любое выражение может быть явно преобразовано в тип «cv void». Значение выражения отбрасывается.

(void)expr Предполагается, что ничего не делать для результирующего значения любого выражения, но если бы он вызывал ваш оператор преобразования, он бы ничего не отбрасывал.Поэтому они запрещают использование operator void в конверсиях.


Почему бы не сделать так, чтобы идентификатор типа конверсии был void?Кто знает, но имейте в виду, что это не полностью бесполезно:

struct foo
{
    operator void()
    {
        std::cout << "huh?" << std::endl;
    }

};

typedef void (foo::*void_function)();

foo f;
void_function func = &foo::operator void;

(f.*func)(); // prints "huh"
f.operator void(); // also does (which you knew)

Это все еще технически потенциально полезно для что-то , так что, возможно, этого достаточно, чтобы не делатьон плохо сформирован.

...