Ключевое слово для класса pinned

dix75
dix75

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

struct A {
    virtual void exec() = 0;
    virtual void doSMT() = 0;
    virtual ~A() {}
};

struct B: A {
    virtual void exec() override final {}
};

struct C final : B  {
    virtual void doSMT() override final {}
    void clear() {}
};


int main()
{
    C c;
    c.exec();
    c.clear();
}

Вместо final  в классе использовать pinned (над словом можно поработать)

Вместо всего кода, компилятор понимал бы, что-то типа этого

struct C   {
    void exec() {}
    void doSMT() {}
    void clear() {}
};

int main()
{
    C c;
    c.exec();
    c.clear();
}

Даже 


p.s.

  1. Ключевое слово рабочее, можно изменить
  2. Слово sealed не приемлемо так как имеет другой смысл (из других языков)
  3. Делегирование данных свойст ключевому слову final невозможно, т.к. на текщий момент, оно имеет другой смысл и расширение свойст врядли применимо
  4. В данном случаи не хочется платить за виртуальность, которая не нужна.
-2
рейтинг
9 комментариев
yndx-antoshkka
Не до конца понимаю суть предложения. В данный момент переменные класса помеченного final будет звать виртуальные функции как встроенные (в обход всей виртуализации):

struct C final : B {
virtual void doSMT() override final {}
void clear() {}
};


int main()
{
C c;
c.exec(); // same as c.C::exec();
c.clear(); // same as c.C::clear();
}
yndx-antoshkka
dix75
yndx-antoshkka,
1. >> В данный момент переменные класса помеченного final будет звать виртуальные функции как встроенные (в обход всей виртуализации):
Где такое написано в стандарте такого нет.(Не нашел, был бы признателен , если ткнули пальцем)
2. Специально проверил asm для gcc.
vtable for C:
.quad 0
.quad typeinfo for C
.quad B::exec()
.quad C::doSMT()
.quad C::~C()
.quad C::~C()
Конечно это не показатель.
3. Хотелось бы видеть то, что для класса С (не будет созаваться виртуальная таблица и др., т.е. отсутствие дополнительных накладных расходов).
А чистый класс, в котором для компилятора все известо (все вируальные функции-член и данные-член),
Очень упрощенно (появляется некая разновидность POD типа).
dix75
yndx-antoshkka
> 1.
В стандарте нет, но в нём редко прописываются оптимизации. В добавок данную оптимизацию не всегда можно произвести. Информация о том что GCC оптимизирует на основе final есть вот тут gcc.gnu.org/gcc-4.9/changes.html "Devirtualization now takes into account anonymous name-spaces and the C++11 final keyword."

> 2.
> 3.
Если pinned должен ещё убирать таблицу виртуальных функций из базовых классов и всё их содержимое переносить внутрь класса С... тогда это очень интересное предложение, но возникает множество вопросов:
1. Если тело классов A и B объявлено в отдельном cpp файле, то у нас нет возможности при генерации кода для C сообщить в другую единицу трансляции о том, что все виртуальные вызовы внутри A и B надо девиртуализировать и вызывать функции класса C
2. Сломается dynamic_cast<C> и catch(A&). При этом для некоторых случаев будет срабатывать, а для некоторых - не будет. Вообще не понятно, как компилятору с таким работать, когда класс A может быть классом с vtable или без него одновременно.
yndx-antoshkka
ru.night.beast
yndx-antoshkka> 3
проще всего сделать так, чтобы компилятор воспринимал класс С как отдельный класс без базы. останутся проблемы 1, но по крайней мере 2 решится.

ну и возникает вопрос в практической нужности всего этого.
как понимаю, это что-то вроде желания иметь mixin в классе.
ru.night.beast
ru.night.beast
тут подумалось что если все сделать через агрегирование с автоматической генерацией функций, то с 1 и 2 не должно быть проблем.
ru.night.beast
dix75
yndx-antoshkka,
1. Возможность оптимизации основанную на разбрасывании кода в различных единицах трансляции думаю производители компиляторов лучше ответят на этот вопрос.
2. dynamic_cast сломается , думаю здесь больше сломается. такие вещи и не предпологаются использовать, в любом случаи это будет неопределенное поведение и каждый в праве выбирать, что ему нужно.
3. Лучше дать компилятору право выбирать, т.е сделать это ключевое слово как рекомендацию компилятору на выполнение данного действия
dix75
dix75
ru.night.beast,
Практическая значимость, в отсутствии дополнительных накладных расходов (виртуальная таблица и др).
Очень часто базовые классы создаются как интерфейсы(только для переопределения определенных методов) и их использование не предпологается в виртуальности.
dix75
yndx-antoshkka
Как верно заметил ru.night.beast@, если при таком pinned наследовании pinned класс воспринимать как класс без наследования - тогда организовать подобное можно. Базовые классы перестанут быть доступными и кастования от базового класса к pinned классу тоже будет приводить к ошибке компиляции.

Всё ещё непонятно, как решать проблему 1). Многие компиляторы не подразумевают кодогенерацию во время линковки, или подобная кодогенерация существенно замедлит линковку, даже в отладочной сборке. Разработчики компиляторов будут против.

Есть идеи как перенести кодогенерацию на этап компиляции?
yndx-antoshkka
ru.night.beast
ru.night.beast
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).