C++ Logo

std-proposals

Advanced search

Re: [std-proposals] declfunc - parameters deduced from arguments

From: Gašper Ažman <gasper.azman_at_[hidden]>
Date: Thu, 6 Jun 2024 00:06:57 +0100
Thanks for the typo corrections.

The rest is an extra feature that is orthogonal to declcall and needs its
own paper.

On Wed, Jun 5, 2024, 23:37 Frederick Virchanza Gotham via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On Wed, Jun 5, 2024 at 4:46 PM Giuseppe D'Angelo wrote:
> >
> > How is this different from
> >
> > https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2825r2.html
>
>
> At the beginning of the paper is:
>
> template <typename R, typename Args...>
> struct my_erased_wrapper {
> using fptr = R(*)(Args_...);
> fptr erased = +[](my_erased_wrapper* self, auto&&... args_) -> R {
> return self->fptr(std::forward<decltype>(args_)...);
> };
> };
>
> Observation 1: typename Args... is a typo for typename... Args
> Observation 2: It says "self->ptr" but 'ptr' isn't a member (it's a type)
>
> declcall fails for constructors and destructors, and maybe this is
> fine, but an alternative could be for it to return a member function
> pointer. So for example if you had:
>
> struct S {
> int n;
> S(int const arg) : n(arg) {}
> S(double const arg) : n( static_cast<int>(arg + 0.5) ) {}
> };
>
> and then if you were to do:
>
> declcall( S(7. 6) )
>
> then it could return the address of the double-accepting-constructor
> inside a "void (S::*)(double)". Then we could do the following:
>
> int main(void)
> {
> S var(5);
> var.~S();
> constexpr auto mfp = declcall( S(6.2) );
> (var.*mfp)(6.3);
> }
>
> Similarly, if you were to write:
>
> declcall( std::declval<S&>().~S() )
>
> then it could return the address of the destructor inside a "void
> (S::*)(void)", and then we could do:
>
> int main(void)
> {
> S var(5);
> constexpr auto mfp = declcall( std::declval<S&>().~S() )
> (var.*mfp)();
> ::new(&var) S(6);
> }
>
> C++ has never allowed us to take the address of a constructor or
> destructor, but this has always been a needless restriction. Getting
> the address of a destructor isn't so much of a big deal since we can
> alternatively take the address of the following function:
>
> template<typename T>
> constexpr void call_destructor(T *const p) noexcept(noexcept(p->~T()))
> {
> p->~T();
> }
>
> However, being able to take the address of a constructor with declcall
> would be helpful since we can't take the address of the following
> function without knowing what conversions of arguments will take
> place:
>
> template<typename T, typename... Params>
> constexpr void call_constructor(T *const p, Params&&... args)
> {
> std::construct_at<T>( p, std::forward<Params>(args)... );
> }
>
> So I'm in favour of being able to use declcall to get the addresses of
> constructors and destructors.
>
> And just one last thing . . . and it's not particularly relevant to
> declcall . . . but it always bugged me that constructors and
> destructors were the same name as the class . . . I don't know why
> Bjarne did that . . . it would have made so much more sense for them
> to be normal member functions which return 'void' and are named
> "_Constructor" or "_Destructor". I'd like if C++26 allowed us to
> write:
>
> struct S {
> void _Constructor(void) {}
> };
>
> instead of:
>
> struct S {
> S(void) {}
> };
>
> meaning we could simply do:
>
> void (S::*)(void) = &S::_Constructor;
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2024-06-05 23:07:10