Возможность явно указать квалификатор метода в момент вызова.

stepsoft
stepsoft

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

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

struct A
{
    void method ();
    void method () const;
};

void foo ()
{
    A value;

    // использовать
    value.const method();

    // вместо
    const A & alias;
    alias.method();

    // или вместо
    alias.сmethod();
}

Выше преставлен упрощенный пример. Например, если использовать доступ к методам через элементы контейнера или умный указатель, или пользовательский тип, реализующий оператор ->, то можно было бы писать так:

::std::shared_ptr< A > pointer = ::std::make_shared< A >();
pointer->const method();

Подобная семантика похожа, например, на явное указание template при вызове шаблонного метода

struct A
{
    template < typename _Type >
    void method ();
}

template < typename _T >
void foo ()
{
    A value;
    value.template method< _T >();
}
-3
рейтинг
8 комментариев
Andrey Davydov

В С++17 добавили функцию as_const с помощью которой Ваш пример с alias станет покороче. К тому же получается консистентно с выбором перегрузки с нужным ref-qualifier:

std::move(value).method()     // для выбора method() &&
std::as_const(value).method() // для выбора method() const &

Явное указание template нужно только в dependent коде для правильного парсинга, но не для выбора нужной перегрузки функции.

Andrey Davydov
stepsoft

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 - это был пример схожей семантики, но не способа применения.

stepsoft
Обновлено 
stepsoft

Andrey Davydov, не понял контекст применения

std::move(value).method()     // для выбора method() &&
stepsoft
Andrey Davydov

stepsoft, а почему в Вашем примере константные методы возвращат неконстантные указатели?

Andrey Davydov
Andrey Davydov

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
}
  
Andrey Davydov
stepsoft

Andrey Davydov, такое бывает и не редко, например

- предполагается создание члена класса при первом обращении к неконстантному методу.
- реализуется COW и неконстантный метод может перераспределить член класса.
- может возвращаться указатель для формирования ассоциативной связи с членом класса.

Не всегда константный метод должен возвращать константный тип. И можно в примере указатель заменить на сам тип.

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();
}
stepsoft
stepsoft

Andrey Davydov, Использование разных видов ссылок и применение квалификаторов (mutable, const, volatile) - это взаимодополняющие вещи. Применение одного не исключает применение другого.

stepsoft
languagelawyer

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1992/WG21%201992/X3J16_92-0136%20WG21_N0212.pdf

languagelawyer
Обновлено 
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).
Все предложения