Aidar
Треитсы
Aidar
Это фича а не ограничение
Constantine
Во! Придумал синтаксис. Хочу для виртуальных функций два дополнительных модификатора ref-значения static и constexpr. struct base { virtual int get_attribute() constexpr = 0; }; struct derived : base { virtual int get_attribute() constexpr override { return 1; } };
Constantine
Модификатор 'static' означает, что в теле функции не определен this; модификатор 'constexpr' дополнительно означает, что сама функция должна быть constexpr
Constantine
А причем тут виртуальность?)
При том, что это - виртуальная функция со всеми вытекающими последствиями
Constantine
В частности, модификатор 'static' не создает полноценно статическую функцию, он лишь гарантирует, что возвращаемое значение зависит только от динамического типа объекта
Constantine
В случае с constexpr компилятор имеет возможность вписать в таблицу виртуальных функций непосредственно результат вычисления constexpr выражения
usernameak
а есть
usernameak
а есть какой то враппер d3d9->opengl на линукс?
usernameak
мне чтобы не вайн
usernameak
только dx
Александр
Да и сейчас это всё реализуемо
Constantine
Это не обязательно const
Constantine
И да, это не реализуемо без проверок
🐙 Antony
Не хочется портить вам счастье, но если объект содержит виртуальные функции, его нельзя сделать constexpr
Александр
Чем ломается?
Например, хранением в таблице виртуальных функций не функции, а значения
Constantine
Не хочется портить вам счастье, но если объект содержит виртуальные функции, его нельзя сделать constexpr
Антон, подразумевается, что сама по себе функция является constexpr, грубо говоря как если бы она была в точности так же написана как статическая функция класса
Александр
В текущем стандарте языка все эти хотелки и так работают, просто да, где-то лишний раз передаётся this, который фактически не требуется
Constantine
Не хочется портить вам счастье, но если объект содержит виртуальные функции, его нельзя сделать constexpr
Т.е. подразумевается, что модификатор 'static' равносилен требованию "функция возвращает результат статической функции (тело функции) этого же класса с теми же параметрами", модификатор constexpr "функция возвращает результат статической constexpr функции (тело функции) этого же класса с теми же параметрами"
Constantine
struct base { virtual int get_attribute() constexpr = 0; }; //предложение struct derived : base { virtual int get_attribute() constexpr override { return 1; } }; //развертка в действующий стандарт struct derived : base { static constexpr int get_attribute__inner() { return 1; }; virtual int get_attribute() override { return get_attribute__inner(/*форвард аргументов*/); } };
Constantine
можно макросами обмазать
🐙 Antony
предлагаю вместо virtual использовать override
Constantine
т.е. начинать декларацию с override?
🐙 Antony
Не, фигня получается struct base { override static constexpr int get_attribute(); };
Крылатый
override уже ведь занят.
Constantine
в данном случае речь идет о наложении дополнительных требований на тело функции
Constantine
весьма непонятен вопрос сигнатуры такой функции
usernameak
virtual в таком случае должен резолвиться на этапе компиляции
Constantine
он не может быть зарезолван
Крылатый
constvirual
Крылатый
Вводим новое
Constantine
struct base { virtual int get_attribute() constexpr = 0; }; struct derived : base { virtual int get_attribute() constexpr override { return 1; } }; void foo(base const& b) { b.get_attribute(); //значение? //base::get_attibute(); //ошибка компиляции derived::get_attibute(); //все-таки должно быть нормально }
Диджитал
реальное применение можешь озвучить?
Constantine
сериализация объектов с фабрикой по имени
Constantine
фабрика по имени создает объект конкретного типа и безумно хочет, чтобы любой созданный ей объект в ответ на запрос имени возвращал то же самое
Constantine
сейчас фабрика в этом случае может использовать map и RTTI
Constantine
что является ручной реализацией vtbl по сути
Berkus
вряд ли из-за одного маргинального юзкейса это надо тащить прямо в язык
Constantine
почему маргинального?
Berkus
ну потому что это и так уже можно сделать с RTTI
Диджитал
я вижу только один смысл тащить значение в vtbl - избежать лишнего вызова
Constantine
реализация map+RTTI позволяет вообще не использовать виртуальные функции
Диджитал
что нужно только в условиях жестких требований к производительности
Constantine
так и не надо
удалить виртуальные функции из языка как сахар?)
Constantine
на самом деле, я уверен, юзкейз можно найти в любой библиотеке с динамическим полиморфизмом
Constantine
Это какой-то софизм. Язык для программ, а не язык - вещь в себе
Nik
Можно пойти дальше и потребовать возможность задавать кастомные атрибуты
Constantine
Я все еще уверен, что в любой реализации есть такие функции
Constantine
И есть контракты на уровне оговорок, которые я предлагаю в язык
Constantine
Просто STL совершенно не использует динамический полиморфизм
Constantine
Да, но это совершенно невозможно в разработке хоть немного сложной программы
Constantine
При этом нет ни одного способа преобразовать контракты статического полиморфизма "задано constexpr поле" в динамический
Constantine
Например, фактическая реализация std::function после потери типа не может потребовать проверить из внутреннего интерфейса по контракту "is_nothrow_move_constructible"
Constantine
Кстати, надо запомнить, годные аргументы для преамбулы
Диджитал
пока что звучит так, что тебе скорее нужны хитрые ассерты, а не правка vtbl
Constantine
это невозможно проверить никаким ASSERT-ом, потому что это статическая проверка
Constantine
на MSC это очень условно можно проверить ассертом, передав 0 в качестве this в конкретную функцию
Constantine
по ISO это UB
Диджитал
я про статический ассерт и говорил
Constantine
статический ассерт в данном случае невозможен в принципе, я не могу проверить тело функции
Диджитал
и нет, я не подразумевал. что это можно сделать существующими средствами, возможно, просто их расширить
Constantine
внедрение интроспекции уровня чтения кода действительно решит эту проблему, но является невозможной задачей
Диджитал
если потребовать определения тела в хедере - то почему невозможной?
Constantine
потому что тело функции иногда оптимизируют
Constantine
функции после компиляции может вообще не существовать
Constantine
забавно, пример действительно есть в реализации std::function в MSC virtual const _XSTD2 type_info& _Target_type() const _NOEXCEPT = 0;
Constantine
http://en.cppreference.com/w/cpp/utility/functional/function/target_type
Диджитал
так это здесь неважно, важно, чтобы функция имела вид return constexpr
Constantine
и как это проверить через static_assert?
Диджитал
ввести новый тип ассерта
Constantine
и что он должен сделать? вызвать функцию, которая не помечена constexpr?