Re: auto и proxy-объекты
От: sergii.p  
Дата: 11.11.25 13:34
Оценка: 6 (1)
Здравствуйте, Marty, Вы писали:

M>Если я напишу

M>
M>auto a = myMap["aaa"];
M>


более классический пример

std::vector<bool> priorities() { ... }
...
bool priority1 = priorities()[1]; // ok
auto priority2 = priorities()[2]; // UB


M>Как это сейчас разруливается?


вроде никак.
Re: auto и proxy-объекты
От: Кодт Россия  
Дата: 11.11.25 23:50
Оценка: 6 (1)
Здравствуйте, Marty, Вы писали:

M>то я же получу не mapped_type, а Proxy, а со ссылкой вообще висяк получу.

M>Как это сейчас разруливается?

Поскольку на уровне языка различить — прокси это или окончательное значение — невозможно, то без лишней писанины и административных мер — никак.

Первая административная мера — придать проксям семантику указателя.
И тогда явно
auto p = map[key];
auto v = *p;

Заодно, это решает проблему множественного опосредования. Сколько раз опосредовано, столько звёздочек напихать.

Вторая административная мера даёт больше писанины в одних местах и меньше — в других.
Это ввести концепт "прокси" и функцию распаковки
template<class T> concept Proxy = .....;

template<class T> using proxee_t = .....;

template<Proxy T> auto proxee(T&& p) -> proxee_t<T> { ..... }

// и дефолтная реализация этой функции для не-прокси-типов
template<class T> auto&& proxee(T&& v) { return std::forward<T>(v); }


(дизайн этих шаблонов не буду сейчас приводить, там есть над чем разнообразно подумать, но это заслонит идею)

и пользоваться
auto v = proxee(map[key]);


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

Правда, надо заметить, что такие специализации чреваты невменяемыми ошибками нарушения ODR, особенно, на концептах.
То есть, ключевые специализации должны оказаться как можно ближе к объявлению прокси-типа, и чтобы никто не вклинился между ними и не инстанцировал основную дефолтную версию концепта и-или функции.
Перекуём баги на фичи!
Re[5]: auto и proxy-объекты
От: so5team https://stiffstream.com
Дата: 12.11.25 07:23
Оценка: +1
Здравствуйте, Marty, Вы писали:

M>Порядок обхода map определяется порядком добавления ключей. Если ключ не добавляется, а перезаписывает имеющееся значение, то могут быть варианты: а) запретить (кинуть исключение) б) обновить на месте в) переместить в конец


Логика мне непонятна (как и многое из того, что вы здесь показываете).

Такое впечатление, что вы в очередной раз делаете что-то странное, поэтому и отгребаете приключения.

Думается, что если map -- это ваш контейнер, то вы можете просто запретить его operator[] возвращать неконстантную ссылку.
Тогда у вас не получится заменить значение по уже имеющемуся ключу. Для такой замены нужно будет использовать другой метод. Внутри которого вы сможете делать что вам захочется (хоть обновлять, хоть перемещать в конец). И никакие прокси вам не потребуются.
Re[13]: auto и proxy-объекты
От: so5team https://stiffstream.com
Дата: 14.11.25 04:50
Оценка: +1
Здравствуйте, Marty, Вы писали:

M>>>Ну, вообще-то я как раз хочу сделать так, чтобы это было невозможно, если ты не заметил


S>>Не заметил.


M>Ты какой-то ненаблюдательный


Это вы здесь задаете вопросы в надежде что вам подскажут. Значит внятно и понятно излагать ваши проблемы -- это в ваших интересах.

Из описанного вами я увидел, что у вас из map::operator[] возвращается Proxy, у которого есть оператор присваивания.
Сам факт наличия этого оператора говорит о том, что у вас в дизайне заложено нарушения принципа минимального удивления.
Но из описанного так же видно, что вы хотите этот самый Proxy с этим самым нарушением сохранить. Просто вам нужно как-то подружить его с auto из современного С++. Т.е. пусть хитровывернутый дизайн останется, но без возможности получить повисшие ссылки из-за auto.
auto и proxy-объекты
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 10.11.25 21:19
Оценка:
Здравствуйте!

Вот у меня есть допустим какой-то мой map, есть там key_type, mapped_type...

Для обычного map я напишу:
auto  a = m["aaa"];
auto& b = m["bbb"];


И всё будет хорошо. Но. Раньше можно было использовать прокси объекты:
class Proxy;

class MyMap
{
//...
Proxy operator[](string key)
//..

};

//..

class Proxy
{
//...
operator mapped_type()
//...

Proxy(const mapped_type&m)
//...

};


И всё работало, потому что не было auto, а надо было явно выписывать тип

А теперь с auto как оно работает?

Если я напишу
auto a = myMap["aaa"];


то я же получу не mapped_type, а Proxy, а со ссылкой вообще висяк получу.

Как это сейчас разруливается?
Маньяк Робокряк колесит по городу
Re[2]: auto и proxy-объекты
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 12.11.25 06:29
Оценка:
Здравствуйте, Кодт, Вы писали:

Тут вопрос такой — в общем случае пользователь же не догадывается, что operatorp[] возвращает прокси, и привыкши писать auto с лёгким сердцем это сделает.

Семантика указателя, поломает способ с auto при следующей попытке использования auto переменной. Но. Я прокси делаю для того, чтобы отловить и специальным образом обработать ситуацию
map[key] = value;


Семантика указателя это тоже поломает
Маньяк Робокряк колесит по городу
Re[3]: auto и proxy-объекты
От: so5team https://stiffstream.com
Дата: 12.11.25 06:53
Оценка:
Здравствуйте, Marty, Вы писали:

M>Но. Я прокси делаю для того, чтобы отловить и специальным образом обработать ситуацию

M>
M>map[key] = value;
M>


Интересно, а что можно ловить в этой ситуации? И, главное, зачем?
Re[4]: auto и proxy-объекты
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 12.11.25 07:06
Оценка:
Здравствуйте, so5team, Вы писали:

M>>Но. Я прокси делаю для того, чтобы отловить и специальным образом обработать ситуацию

M>>
M>>map[key] = value;
M>>


S>Интересно, а что можно ловить в этой ситуации? И, главное, зачем?


Порядок обхода map определяется порядком добавления ключей. Если ключ не добавляется, а перезаписывает имеющееся значение, то могут быть варианты: а) запретить (кинуть исключение) б) обновить на месте в) переместить в конец
Маньяк Робокряк колесит по городу
Re[6]: auto и proxy-объекты
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 12.11.25 18:12
Оценка:
Здравствуйте, so5team, Вы писали:

M>>Порядок обхода map определяется порядком добавления ключей. Если ключ не добавляется, а перезаписывает имеющееся значение, то могут быть варианты: а) запретить (кинуть исключение) б) обновить на месте в) переместить в конец


S>Логика мне непонятна (как и многое из того, что вы здесь показываете).


Я заметил


S>Такое впечатление, что вы в очередной раз делаете что-то странное, поэтому и отгребаете приключения.


Возможно


S>Думается, что если map -- это ваш контейнер, то вы можете просто запретить его operator[] возвращать неконстантную ссылку.


Контейнер мой, но запретить — не могу


S>Тогда у вас не получится заменить значение по уже имеющемуся ключу. Для такой замены нужно будет использовать другой метод. Внутри которого вы сможете делать что вам захочется (хоть обновлять, хоть перемещать в конец). И никакие прокси вам не потребуются.


Контейнер мой, но передаётся в чужой код, который кладёт значения в map через operator[]
Маньяк Робокряк колесит по городу
Re[7]: auto и proxy-объекты
От: so5team https://stiffstream.com
Дата: 13.11.25 03:50
Оценка:
Здравствуйте, Marty, Вы писали:

S>>Логика мне непонятна (как и многое из того, что вы здесь показываете).


M>Я заметил


А могли бы и задуматься почему ваши гениальные замыслы не находят понимания.

S>>Тогда у вас не получится заменить значение по уже имеющемуся ключу. Для такой замены нужно будет использовать другой метод. Внутри которого вы сможете делать что вам захочется (хоть обновлять, хоть перемещать в конец). И никакие прокси вам не потребуются.


M>Контейнер мой, но передаётся в чужой код, который кладёт значения в map через operator[]


Значит и вы, и ваши пользователи должны страдать, ибо нарушается принцип наименьшего удивления.

Если хочется извращений, то попробуйте поэкспериментировать с методами вашего прокси, которые будут разрешены только для случая rvalue reference.
Что-то типа:
class proxy {
public:
  void f() &&;
  ...
};

Тогда метод f() можно будет вызвать у объекта proxy только если это временный объект.
А вот если кто-то его сохранил на стеке и пытается вызвать f по обычной или конст-ссылке, то компилятор ударит по рукам: https://wandbox.org/permlink/s5hlLuSfHKbEIg0g
Re[8]: auto и proxy-объекты
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 13.11.25 07:11
Оценка:
Здравствуйте, so5team, Вы писали:

S>>>Логика мне непонятна (как и многое из того, что вы здесь показываете).


M>>Я заметил


S>А могли бы и задуматься почему ваши гениальные замыслы не находят понимания.


Ну, они мало у кого не находят понимания


S>>>Тогда у вас не получится заменить значение по уже имеющемуся ключу. Для такой замены нужно будет использовать другой метод. Внутри которого вы сможете делать что вам захочется (хоть обновлять, хоть перемещать в конец). И никакие прокси вам не потребуются.


M>>Контейнер мой, но передаётся в чужой код, который кладёт значения в map через operator[]


S>Значит и вы, и ваши пользователи должны страдать, ибо нарушается принцип наименьшего удивления.


И в чем же нарушение?


S>Если хочется извращений, то попробуйте поэкспериментировать с методами вашего прокси, которые будут разрешены только для случая rvalue reference.

S>Что-то типа:
S>
S>class proxy {
S>public:
S>  void f() &&;
S>  ...
S>};
S>

S>Тогда метод f() можно будет вызвать у объекта proxy только если это временный объект.
S>А вот если кто-то его сохранил на стеке и пытается вызвать f по обычной или конст-ссылке, то компилятор ударит по рукам: https://wandbox.org/permlink/s5hlLuSfHKbEIg0g

Да, это выглядит интересно. А как такая конструкция называется, и в каких разделах описана?
Маньяк Робокряк колесит по городу
Re[9]: auto и proxy-объекты
От: so5team https://stiffstream.com
Дата: 13.11.25 07:27
Оценка:
Здравствуйте, Marty, Вы писали:

S>>Значит и вы, и ваши пользователи должны страдать, ибо нарушается принцип наименьшего удивления.


M>И в чем же нарушение?


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

Т.е. вполне можно понять, когда сам по себе operator[] для map может изменить порядок следования (скажем, если operator[] обновляет "метку времени" последнего обращения к объекту). Но когда это делает не operator[], а последующие действия с самим объектом, то это из категории "внезапно".

Кроме того, как я понимаю, у вас вот такая ситуация:
struct A {
  int _a;
  long _b;
};

Marty::TrickyMap<int, A> map;
...
map[ 0 ] = A{ ._a = 3, ._b = 4 };

будет менять порядок следования элементов, т.к. вы видите полную замену содержимого. Но вот так:
map[ 0 ]->_a = 3;
map[ 0 ]->_b = 4;

порядок следования уже не поменяется. Хотя объект полностью изменит свое содержимое.

M>Да, это выглядит интересно. А как такая конструкция называется, и в каких разделах описана?


https://en.cppreference.com/w/cpp/language/member_functions.html -- в разделе Member functions with ref-qualifier
Re[10]: auto и proxy-объекты
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 13.11.25 18:54
Оценка:
Здравствуйте, so5team, Вы писали:

S>>>Значит и вы, и ваши пользователи должны страдать, ибо нарушается принцип наименьшего удивления.


M>>И в чем же нарушение?


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


S>Т.е. вполне можно понять, когда сам по себе operator[] для map может изменить порядок следования (скажем, если operator[] обновляет "метку времени" последнего обращения к объекту). Но когда это делает не operator[], а последующие действия с самим объектом, то это из категории "внезапно".


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


S>Кроме того, как я понимаю, у вас вот такая ситуация:

S>
S>struct A {
S>  int _a;
S>  long _b;
S>};

S>Marty::TrickyMap<int, A> map;
S>...
S>map[ 0 ] = A{ ._a = 3, ._b = 4 };
S>

S>будет менять порядок следования элементов, т.к. вы видите полную замену содержимого. Но вот так:
S>
S>map[ 0 ]->_a = 3;
S>map[ 0 ]->_b = 4;
S>

S>порядок следования уже не поменяется. Хотя объект полностью изменит свое содержимое.

Не понял, а как/за счёт чего это будет работать?


M>>Да, это выглядит интересно. А как такая конструкция называется, и в каких разделах описана?


S>https://en.cppreference.com/w/cpp/language/member_functions.html -- в разделе Member functions with ref-qualifier


Спасибо
Маньяк Робокряк колесит по городу
Re[11]: auto и proxy-объекты
От: so5team https://stiffstream.com
Дата: 14.11.25 03:52
Оценка:
Здравствуйте, Marty, Вы писали:

M>Ну, вообще-то я как раз хочу сделать так, чтобы это было невозможно, если ты не заметил


Не заметил.
Re[12]: auto и proxy-объекты
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 14.11.25 04:11
Оценка:
Здравствуйте, so5team, Вы писали:

M>>Ну, вообще-то я как раз хочу сделать так, чтобы это было невозможно, если ты не заметил


S>Не заметил.


Ты какой-то ненаблюдательный
Маньяк Робокряк колесит по городу
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.