Я читал раздел 13.5 после опровержения понятия, что встроенные операторы не участвуют в разрешении перегрузки, и заметили, что в разделе operator->*
нет раздела. Это всего лишь общий двоичный оператор.
Его братья, operator->
, operator*
и operator[]
, все должны быть нестатическими функциями-членами. Это исключает определение перегрузки свободной функции оператору, обычно используемому для получения ссылки от объекта. Но необычный operator->*
не учитывается.
В частности, operator[]
имеет много общего. Он двоичный (они пропустили прекрасную возможность сделать его n-ary), и он принимает какой-то контейнер слева и какой-то локатор справа. Его раздел специальных правил, 13.5.5, похоже, не имеет никакого фактического эффекта, кроме как запретить бесплатные функции. (И это ограничение даже исключает поддержку коммутативности!)
Так, например, это совершенно законно:
#include <utility>
#include <iostream>
using namespace std;
template< class T >
T &
operator->*( pair<T,T> &l, bool r )
{ return r? l.second : l.first; }
template< class T >
T & operator->*( bool l, pair<T,T> &r ) { return r->*l; }
int main() {
pair<int, int> y( 5, 6 );
y->*(0) = 7;
y->*0->*y = 8; // evaluates to 7->*y = y.second
cerr << y.first << " " << y.second << endl;
}
Легко найти использование, но альтернативный синтаксис не так уж плох. Например, масштабированные индексы для vector
:
v->*matrix_width[2][5] = x; // ->* not hopelessly out of place
my_indexer<2> m( v, dim ); // my_indexer being the type of (v->*width)
m[2][5] = x; // it is probably more practical to slice just once
Неужели комитет по стандартам забыл предотвратить это, считалось ли это слишком уродливым, чтобы беспокоиться, или существуют ли реальные случаи использования?