Russian Qt Forum
Март 29, 2024, 15:44 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3 ... 5   Вниз
  Печать  
Автор Тема: Шаблонный виртуал  (Прочитано 28412 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Сентябрь 01, 2017, 11:04 »

Добрый день

Давеча мелькнула фраза
Цитировать
виртуальный метод нельзя сделать шаблонным (надеюсь понятно почему)
Конечно это так, и это все знают. Но ПОЧЕМУ? В чем причина такого ограничения?

Спасибо
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #1 : Сентябрь 01, 2017, 11:55 »

Потому что нельзя сформировать vtbl для бесконечного множества вариантом шаблонного методов.
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #2 : Сентябрь 01, 2017, 15:03 »

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

Да, но бесконечности ведь нет. Шаблоны ведь это просто подсказка компилятору "скопируй этот метод заменив T на double", то есть сахар для перегрузки. А ведь все типы, которые будут использованы для данного метода, известны заранее на этапе компиляции. Следовательно и vtbl можно сформировать. Но это теория. А на практике в С++ куча ограничений из-за сложности реализации какой-то фичи в компиляторе. То есть фичи нет просто потому, что её сложно сделать, и всё. Так и здесь.
« Последнее редактирование: Сентябрь 01, 2017, 15:06 от Alex Custov » Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #3 : Сентябрь 01, 2017, 23:55 »

Добрый день

Давеча мелькнула фраза
Цитировать
виртуальный метод нельзя сделать шаблонным (надеюсь понятно почему)
Конечно это так, и это все знают. Но ПОЧЕМУ? В чем причина такого ограничения?

Спасибо

технических ограничений не существует.

Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #4 : Сентябрь 02, 2017, 00:00 »

Шаблоны ведь это просто подсказка компилятору "скопируй этот метод заменив T на double", то есть сахар для перегрузки. А ведь все типы, которые будут использованы для данного метода, известны заранее на этапе компиляции. Следовательно и vtbl можно сформировать. Но это теория. А на практике в С++ куча ограничений из-за сложности реализации какой-то фичи в компиляторе. То есть фичи нет просто потому, что её сложно сделать, и всё. Так и здесь.

все верно кроме "фичу слишком сложно реализовать".

фичи нет не потому, что сложно сделать,
а потому, что видимо комитет не видит в ней надобности.

с другой стороны, комитет мыслит глобальнее.
они на с++20 анонсировали статическую рефлексию.
в теории можно будет делать вещи позаковыристее,
чем какой то там шаблоно-виртуал.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Сентябрь 02, 2017, 05:29 »

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

Насколько я понял, дело в следующем
А ведь все типы, которые будут использованы для данного метода, известны заранее на этапе компиляции. Следовательно и vtbl можно сформировать.
Да, но тут одна бяка: "инстанциация" может случиться из другой единицы трансляции (по-простому из др .cpp файла). И тогда надо что-то делать с теми файлами что уже откомпилены, как-то менять VMT классов что в них - а нынешняя технология компиляторов этого не позволяет, мол, откомпилено - значит все, готово и изменению не подлежит.

они на с++20 анонсировали статическую рефлексию.
А что это?
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #6 : Сентябрь 02, 2017, 11:36 »

Про "бесконечности ведь нет", "технических ограничений не существует" и "все верно кроме "фичу слишком сложно реализовать"" как-то я сомневаюсь. С библиотеками тоже сложностей нет?

Например:
1. В библиотеке SomeLibrary есть интерфейс с шаблонным методом
Код
C++ (Qt)
class ISomeClass
{
   ...
   template <class T>
   virtual void doSomething(T value) = 0;
}
и в ней же есть функция, которая создаёт объект с таким интерфейсом, в котором метод реализован, допустим, для типов double и int (но в общем случае не известно, для каких типов).
Код
C++ (Qt)
ISomeClass * makeSomeObject();

2. Приложение использует библиотеку SomeLibrary:
Код
C++ (Qt)
QWidget * widget = new QWidget();
ISomeClass * some_object = makeSomeObject();
some_object->doSomething(widget);

Что должен сделать компилятор?

с другой стороны, комитет мыслит глобальнее.
они на с++20 анонсировали статическую рефлексию.
в теории можно будет делать вещи позаковыристее,
чем какой то там шаблоно-виртуал.
Комитет много чего анонсирует, только доживём ли Веселый.
Записан

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Сентябрь 02, 2017, 12:10 »

Что должен сделать компилятор?
Компилятор может и ничего, а вот линкер мог бы и перестроить VMT(s) c учетом "прибывших"
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #8 : Сентябрь 02, 2017, 12:45 »

Компилятор может и ничего, а вот линкер мог бы и перестроить VMT(s) c учетом "прибывших"
В динамической библиотеке? Улыбающийся
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #9 : Сентябрь 02, 2017, 16:41 »

Про "бесконечности ведь нет", "технических ограничений не существует" и "все верно кроме "фичу слишком сложно реализовать"" как-то я сомневаюсь. С библиотеками тоже сложностей нет?

Например:
1. В библиотеке SomeLibrary есть интерфейс с шаблонным методом
Код
C++ (Qt)
class ISomeClass
{
   ...
   template <class T>
   virtual void doSomething(T value) = 0;
}
и в ней же есть функция, которая создаёт объект с таким интерфейсом, в котором метод реализован, допустим, для типов double и int (но в общем случае не известно, для каких типов).
Код
C++ (Qt)
ISomeClass * makeSomeObject();

2. Приложение использует библиотеку SomeLibrary:
Код
C++ (Qt)
QWidget * widget = new QWidget();
ISomeClass * some_object = makeSomeObject();
some_object->doSomething(widget);

Что должен сделать компилятор?

для шаблонов нет никаких "общих случаев, когда не известно с чем шаблон был инстанцирован".
есть единственный случай, когда компилятор знает точно для каких типов был инстанцирован шаблон.

в какой то момент он знает про int и double,
на этот момент он инстанцировал:
Код:
virtual void doSomething(int  value);
virtual void doSomething(double value);
увидев запись:
Код:
some_object->doSomething(widget);

он просто инстанцирует ещё одну перегрузку:
Код:
virtual void doSomething(QWidget * value);

в отсутствии шаблоно-виртуалов,
все тоже самое можно сделать руками.

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

« Последнее редактирование: Сентябрь 02, 2017, 17:06 от _Bers » Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #10 : Сентябрь 02, 2017, 17:05 »

тут одна бяка: "инстанциация" может случиться из другой единицы трансляции (по-простому из др .cpp файла).

шаблоны имеют иммунитет против "множественного определения" по разным. ед. трансляций.

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

вот вам немножко другой пример "издалека".

рассмотрим простейший класс:

Код:
struct sample{
    static int val;  //где то в sample.cpp:  int sample::val = 33;
};

здесь все просто.
как быть с шаблоном?

Код:
template<class T>
struct sample{
    static int val;  
};
int sample<T>::val = 33; //<--- в какой именно ед. трансляции он будет жить?

стандарт говорит: на усмотрение конкретной реализации.

компилятор, видя "заковыристый" шаблон вообще может породить "скрытную"
ед. трансляции, например.

или определить его в любой первой попавшейся,
которую транслирует.

или вообще во всех подряд,
а линкер потом повыкидывает лишнее.

пока у нас нет нарушений ODR - все конфликты легко устраняются
путем выпиливания избыточных копий инстансов.

в отношении шаблоно-виртуалов мог бы сработать аналогичный механизм.

для каждой ед. трансляции компилятор может нагенерировать отдельную версию vtbl
а линкер, при резолве символов их потом все смержит в одну.

пока нет нарушений ODR, он просто сошьет из нескольких vtbl одну,
выпиливая дубликаты, и добавляя новеньких.

« Последнее редактирование: Сентябрь 02, 2017, 17:20 от _Bers » Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #11 : Сентябрь 02, 2017, 17:19 »

они на с++20 анонсировали статическую рефлексию.
А что это?

времени компиляции можно будет получать всю информацию
о типах/функциях/переменных,
включая неймспейсы.

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

единственное, я так до конца и не понял:
можно ли будет удалять/добавлять/изменять реализацию уже имеющихся классов.

у них затык вышел:
они сделали отдельно друг от дружки прототипы: концепты, модули, статическая рефлексия.
и в итоге не смогли все это вместе подружить.

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

но... реально, пока они там что нибудь родят ещё не мало воды утечет.
хз что у них получится. рефлексию они ещё в 17 обещали.
сейчас я даже насчет 20 не уверен)))

а пока у них только концепты/прототипы/наброски.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #12 : Сентябрь 02, 2017, 20:38 »

для шаблонов нет никаких "общих случаев, когда не известно с чем шаблон был инстанцирован".
есть единственный случай, когда компилятор знает точно для каких типов был инстанцирован шаблон.
Виртуальные методы нужны для их последующего переопределения.
Допустим, вы пишите библиотеку, где в одном из классов описываете шаблонный виртуальный метод, собираете эту библиотеку в dll и отправляете в мир. Все таблицы vtbl уже сформированы и помещены в эту dll.
Теперь пользователь вашей библиотеки решает создать класс-наследник от вашего класса и переопределить эту виртуальную шаблонную функцию, инстанцируя ее своим классом.
Как компилятор/линкер сможет изменить vtbl вашего класса из dll, что-бы сделать возможным вызов клиентского метода, через указатель на базовый класс? Улыбающийся
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #13 : Сентябрь 02, 2017, 21:25 »

для шаблонов нет никаких "общих случаев, когда не известно с чем шаблон был инстанцирован".
есть единственный случай, когда компилятор знает точно для каких типов был инстанцирован шаблон.
Виртуальные методы нужны для их последующего переопределения.
Допустим, вы пишите библиотеку, где в одном из классов описываете шаблонный виртуальный метод, собираете эту библиотеку в dll и отправляете в мир. Все таблицы vtbl уже сформированы и помещены в эту dll.
Теперь пользователь вашей библиотеки решает создать класс-наследник от вашего класса и переопределить эту виртуальную шаблонную функцию, инстанцируя ее своим классом.
Как компилятор/линкер сможет изменить vtbl вашего класса из dll, что-бы сделать возможным вызов клиентского метода, через указатель на базовый класс? Улыбающийся


ему и не нужно ничего изменять.
компилятор сгенерирует код приложения так, что бы при импорте dll,
vtbl на стороне приложения была модифицирована с учетом "новеньких".
« Последнее редактирование: Сентябрь 02, 2017, 21:38 от _Bers » Записан
Bepec
Гость
« Ответ #14 : Сентябрь 02, 2017, 21:59 »

Тогда это нарушает весь текущий принцип dll. Тем самым давая такие просторы для багов/некорретных использований и переборов, что компиляция будет минут по 20 длиться простенькой dll.

PS сам смысл dll что они кроют в себе неизменяемый функционал. А вы предлагаете их превратить в плагины с неопределяемой сложностью.
Записан
Страниц: [1] 2 3 ... 5   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.169 секунд. Запросов: 22.