Closed apolukhin closed 3 years ago
Andrey Davydov, 3 апреля 2018, 18:56 В С++17 добавили функцию as_const с помощью которой Ваш пример с alias станет покороче. К тому же получается консистентно с выбором перегрузки с нужным ref-qualifier:
std::move(value).method() // для выбора method() &&
std::as_const(value).method() // для выбора method() const &
Явное указание template нужно только в dependent коде для правильного парсинга, но не для выбора нужной перегрузки функции.
A, 3 апреля 2018, 21:19 Andrey Davydov, такой подход как ::std::as_const я использую давно и нахожу его неудобным и плохо читаемым.
Вот такой пример, предположим неконстантные методы создают экземпляр объекта на который возвращается указатель, если он еще не создан.
using namespace std;
struct A
{
void method ();
void method () const;
};
struct B
{
A * getA ();
A * getA () const;
};
struct C
{
B * getB ();
B * getB () const;
};
void foo ()
{
C c;
// с использованием as_const
as_const( *as_const( *as_const( c ).getB() ).getA() ).method();
// с указанием квалификатора
c.const getB()->const getA()->const method();
}
Использование as_const добавляет код слева и трудно сказать к чему он относится, когда указание const в месте вызова метода интуитивно понятно.
Насчет template - это был пример схожей семантики, но не способа применения.
A, 3 апреля 2018, 21:33 Обновлено 3 апреля 2018, 21:19
Andrey Davydov, не понял контекст применения
std::move(value).method() // для выбора method() &&
Andrey Davydov, 3 апреля 2018, 21:42 stepsoft, а почему в Вашем примере константные методы возвращат неконстантные указатели?
Andrey Davydov, 3 апреля 2018, 21:48 stepsoft,
не понял контекст применения
struct X { ... };
struct Y {
X & x() &; // #1
X const & x() const &; // #2
X && x() &&; // #3
};
void test(Y y) {
y .x(); // #1
std::as_const(y).x(); // #2
std::move(y) .x(); // #3
}
A, 3 апреля 2018, 21:58 Andrey Davydov, такое бывает и не редко, например
Не всегда константный метод должен возвращать константный тип. И можно в примере указатель заменить на сам тип.
using namespace std;
struct A
{
void method ();
void method () const;
};
struct B
{
A getA ();
A getA () const;
};
struct C
{
B getB ();
B getB () const;
};
void foo ()
{
C c;
// с использованием as_const
as_const( as_const( as_const( c ).getB() ).getA() ).method();
// с указанием квалификатора
c.const getB().const getA().const method();
}
A, 3 апреля 2018, 22:07 Andrey Davydov, Использование разных видов ссылок и применение квалификаторов (mutable, const, volatile) - это взаимодополняющие вещи. Применение одного не исключает применение другого.
languagelawyer, 23 мая 2018, 6:42 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1992/WG21%201992/X3J16_92-0136%20WG21_N0212.pdf
std::as_const
в С++17 вырос как раз из обсуждения похожей идеи. Чтобы воскресить обсуждение решения данной проблемы на уровне языка надо найти кейс, который не покрывается std::as_const
и std::move
и не имеет решения через библиотекчные методы.
Перенос предложения: голоса +1, -4 Автор идеи: A
Не редко декларация класса содержит одноименные методы с одинаковой сигнатурой, но с разными квалификаторами. При этом реализация const методов, обычно, является более легковесной. Решение - дублировать вызов константных методов с помощью неконстантных (например, begin () const и end () const дублировать сbegin () const и сend () const) - не выглядит красивым.
Вероятно, лучшим вариантом была бы возможность явно указать квалификатор вызываемого метода.
Выше преставлен упрощенный пример. Например, если использовать доступ к методам через элементы контейнера или умный указатель, или пользовательский тип, реализующий оператор ->, то можно было бы писать так:
Подобная семантика похожа, например, на явное указание template при вызове шаблонного метода