Комбинированная перегрузка операторов в C ++? - PullRequest
0 голосов
/ 22 декабря 2011

Можно ли перегрузить операторы таким образом, чтобы вы могли захватить определенную комбинацию из них? Например, допустим, у меня есть пользовательский объект myObject типа MyType, где [] уже перегружен для передачи таких вызовов объекту карты. Тем не менее, в случае следующего кода:

int value = myObject["someProp"];

Я уже перегружаю [], но в этом случае я бы хотел знать, когда [] вызывается для объекта в назначении, со ссылкой на тип объекта, который должен быть найден для свойства назначен на. Таким образом, я могу привести значение, полученное из динамического поиска свойства и так далее, и так далее. Любой вклад приветствуется!

Чтобы лучше понять, что именно я пытаюсь сделать, см. Этот мой связанный вопрос .

Ответы [ 5 ]

5 голосов
/ 22 декабря 2011

Нет, вы не можете перегружать тип возвращаемого значения или контекст, в котором появляется вызов (например, в назначении и т. Д.).

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

1 голос
/ 22 декабря 2011

В принципе, это довольно просто сделать: все, что вам нужно, это чтобы ваш оператор возвратил прокси, который затем перегружает операторов, которых вы хотите перехватить.На практике это может вызвать больше, чем несколько проблем;читатели ожидают, что (a <i>op1</i> b) <i>op2</i> c будет иметь ту же семантику, что и T tmp(a <i>ip1</i> b); tmp <i>op2</i> c.Однако есть некоторые распространенные исключения:

  • * * * * * * * * * * * * * * * * * * * * * * * * * *}} в многомерном массиве будет часто возвращать прокси, который определяет само operator[], для поддержки [][]правильно.

  • В более общем случае контейнер, который по каким-либо причинам должен знать, когда изменяется значение, будет иметь operator[], который возвращает прокси;в прокси присваивание определяется как установка значения в контейнере-владельце, и будет существовать оператор преобразования в тип значения для использования в контекстах rvalue.Конечно, это означает, что такие вещи, как m[i][j].funct(), не работают;однако, как правило, такого рода вещи используются для матриц числовых типов, где функции-члены не так уж важны.

  • В тех случаях, когда желательно поддерживать разрешение перегрузки на основецелевой тип (ваш пример), функция может возвращать прокси с перегруженными операторами преобразования.Вы должны быть очень осторожны с этим - перегруженные операторы преобразования часто являются рецептом неоднозначности разрешения перегрузки - но есть достаточно исключений, о которых стоит упомянуть.(Здесь важно то, что результаты оператора всегда будут использоваться для инициализации или присвоения определенному объекту, тип которого определяет, какой оператор преобразования будет вызываться.)

Кстати: я мог бы упомянуть, что в приведенном вами примере нет назначения;это классическая инициализация.В этом случае определение operator[] для возврата прокси-сервера, который определяет operator int() const, хорошо бы сработало.Однако перед тем, как идти по этому пути, вы должны совершенно определенно рассмотреть все варианты использования вашего класса и убедиться, что ни в одном из них фактический тип цели не определен.

1 голос
/ 22 декабря 2011

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

Мне это часто было нужно. В конечном итоге я в конечном итоге собираюсь использовать ряд перегруженных функций или шаблонов, в зависимости от ваших потребностей, например, так:

void lookup( int& v, char const * name );
void lookup( double& c, char const * name );

В случае шаблона я создал глобальные конвертеры и выполнил следующую функцию-член:

template<T>
void lookup( T&v, char const* name ) { v = convert<T>( get(name) ); }

Если вы хотите сохранить возвращаемое значение в качестве поиска, вам придется явно вызывать шаблонную функцию.

   template<T> T get( char const * name ) { ... }

   //use
   int a = obj.get<int>( "name" );
   double b = obj.get<double>( "floaty" );
1 голос
/ 22 декабря 2011

Если вы хотите вычесть типа для подобных вещей, лучше всего вместо этого перегрузить operator() и передать в качестве фиктивного параметра то, что вы собираетесь назначить, т.е.

В прошлом я делал что-то вроде этой работы довольно хорошо.В частности, см., Например:

https://github.com/sgolodetz/hesperus2/blob/master/source/engine/core/hesp/objects/base/ObjectManager.tpp

0 голосов
/ 22 декабря 2011

Нет, вы не можете этого сделать.

Больше того, безумие таково!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...