Сообщение Re[48]: offsetof() без UB от 01.04.2025 8:59
Изменено 01.04.2025 9:03 rg45
Re[48]: offsetof() без UB
Здравствуйте, kov_serg, Вы писали:
_>Это конечно здорово, но это просто обёртка. Она не решает вопроса как такое передавать во внешнюю среду, или принимать из неё подобное.
_>Более того предыдущие указатели можно было сгенерировать руками если нет поддержки c++17. А тут только C++20.
Объект accessor<...> прекрасно заточен под передачу в качестве параметра. Если же ты имеешь в виду внешнюю среду, которая сама по себе сделана через жопу, тогда конечно, вокруг этого нужно будет сделать черезжопные обертки. Какие именно обёртки — будет продиктовано спецификой чережопной внешней среды.
_>ps: А что будет если надо обернуть функцию без параметров void A::g(); ?
Ты тут несколькими постами выше рассказывал, что концепты и констрейнты это легко и просто, а теперь задаешь такие глупые вопросы. Конечно же там следует добавить констрейнты. А также сделать форвардинг параметров. Я намеренно не сделал всего этого, чтобы максимально разгрузить код.
Более полный вариант мог бы выглядеть примерно так:
https://godbolt.org/z/3MEKsr4e3
_>Это конечно здорово, но это просто обёртка. Она не решает вопроса как такое передавать во внешнюю среду, или принимать из неё подобное.
_>Более того предыдущие указатели можно было сгенерировать руками если нет поддержки c++17. А тут только C++20.
Объект accessor<...> прекрасно заточен под передачу в качестве параметра. Если же ты имеешь в виду внешнюю среду, которая сама по себе сделана через жопу, тогда конечно, вокруг этого нужно будет сделать черезжопные обертки. Какие именно обёртки — будет продиктовано спецификой чережопной внешней среды.
_>ps: А что будет если надо обернуть функцию без параметров void A::g(); ?
Ты тут несколькими постами выше рассказывал, что концепты и констрейнты это легко и просто, а теперь задаешь такие глупые вопросы. Конечно же там следует добавить констрейнты. А также сделать форвардинг параметров. Я намеренно не сделал всего этого, чтобы максимально разгрузить код.
Более полный вариант мог бы выглядеть примерно так:
https://godbolt.org/z/3MEKsr4e3
#include <stdio.h>
#include <utility>
template <auto member>
requires (member != nullptr)
struct Accessor
{
template <typename T>
constexpr decltype(auto) operator()(T&& object) const
requires (
requires {std::forward<T>(object).*member;}
and not requires {(std::forward<T>(object).*member)();})
{
return std::forward<T>(object).*member;
}
template <typename T, typename...X>
constexpr decltype(auto) operator()(T&& object, X&&...x) const
requires requires {(std::forward<T>(object).*member)(std::forward<X>(x)...);}
{
return (std::forward<T>(object).*member)(std::forward<X>(x)...);
}
};
template <auto member> constexpr Accessor<member> accessor;
struct A {
int x = 10;
virtual int fn(int y) { return x + y; }
int get() const {return x;}
};
int main() {
A a[1];
auto fn = accessor<&A::fn>;
auto x = accessor<&A::x>;
auto get = accessor<&A::get>;
printf("x=%d fn(20)=%d get=%d\n", x(*a), fn(*a, 20), get(*a));
}
Re[48]: offsetof() без UB
Здравствуйте, kov_serg, Вы писали:
_>Это конечно здорово, но это просто обёртка. Она не решает вопроса как такое передавать во внешнюю среду, или принимать из неё подобное.
_>Более того предыдущие указатели можно было сгенерировать руками если нет поддержки c++17. А тут только C++20.
Объект accessor<...> прекрасно заточен под передачу в качестве параметра. Если же ты имеешь в виду внешнюю среду, которая сама по себе сделана через жопу, тогда конечно, вокруг этого нужно будет сделать черезжопные обертки. Какие именно обёртки — будет продиктовано спецификой чережопной внешней среды.
_>ps: А что будет если надо обернуть функцию без параметров void A::g(); ?
Ты тут несколькими постами выше рассказывал, что концепты и констрейнты это легко и просто, а теперь задаешь такие глупые вопросы. Конечно же там следует добавить констрейнты. А также сделать форвардинг параметров. Я намеренно не сделал всего этого, чтобы максимально разгрузить код.
Более полный вариант мог бы выглядеть примерно так:
https://godbolt.org/z/3MEKsr4e3
При необходимости, разумеется, можно сделать и раздельные аксессоры для членов-функций и для членов-данных, это уже зависит от конкретных требований
_>Это конечно здорово, но это просто обёртка. Она не решает вопроса как такое передавать во внешнюю среду, или принимать из неё подобное.
_>Более того предыдущие указатели можно было сгенерировать руками если нет поддержки c++17. А тут только C++20.
Объект accessor<...> прекрасно заточен под передачу в качестве параметра. Если же ты имеешь в виду внешнюю среду, которая сама по себе сделана через жопу, тогда конечно, вокруг этого нужно будет сделать черезжопные обертки. Какие именно обёртки — будет продиктовано спецификой чережопной внешней среды.
_>ps: А что будет если надо обернуть функцию без параметров void A::g(); ?
Ты тут несколькими постами выше рассказывал, что концепты и констрейнты это легко и просто, а теперь задаешь такие глупые вопросы. Конечно же там следует добавить констрейнты. А также сделать форвардинг параметров. Я намеренно не сделал всего этого, чтобы максимально разгрузить код.
Более полный вариант мог бы выглядеть примерно так:
https://godbolt.org/z/3MEKsr4e3
#include <stdio.h>
#include <utility>
template <auto member>
requires (member != nullptr)
struct Accessor
{
template <typename T>
constexpr decltype(auto) operator()(T&& object) const
requires (
requires {std::forward<T>(object).*member;}
and not requires {(std::forward<T>(object).*member)();})
{
return std::forward<T>(object).*member;
}
template <typename T, typename...X>
constexpr decltype(auto) operator()(T&& object, X&&...x) const
requires requires {(std::forward<T>(object).*member)(std::forward<X>(x)...);}
{
return (std::forward<T>(object).*member)(std::forward<X>(x)...);
}
};
template <auto member> constexpr Accessor<member> accessor;
struct A {
int x = 10;
virtual int fn(int y) { return x + y; }
int get() const {return x;}
};
int main() {
A a[1];
auto fn = accessor<&A::fn>;
auto x = accessor<&A::x>;
auto get = accessor<&A::get>;
printf("x=%d fn(20)=%d get=%d\n", x(*a), fn(*a, 20), get(*a));
}
При необходимости, разумеется, можно сделать и раздельные аксессоры для членов-функций и для членов-данных, это уже зависит от конкретных требований
