Здравствуйте, 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, особенно, на концептах.
То есть, ключевые специализации должны оказаться как можно ближе к объявлению прокси-типа, и чтобы никто не вклинился между ними и не инстанцировал основную дефолтную версию концепта и-или функции.