C++ Logo

std-proposals

Advanced search

Re: [std-proposals] A drift for c++ decorators;

From: zys <dou1984_at_[hidden]>
Date: Sun, 27 Oct 2024 21:59:26 +0800 (CST)
Dear arthur:




I just want to implement a syntactic sugar for "function hook" and make it support member functions. Unfortunately, I did not find relevant content in N3617 and P0834.

If the code is replaced during the pre-compilation period, it will not involve issues related to class inheritance. The override calls order should follow existing C++ rules, so there won't be any override problems. Of course, the developer needs to fix compiler's warnings.

I modified the previous example to better illustrate what I want to achieve.




@print_logs(file_name, file_line) // Execute print_logs before executing add.
intadd(inta, intb)
{
    return a + b;
}
intcommon()
{
    constchar* file_name = __FILE__;
    constint file_line = __LINE__;
    add(1, 2); // print: "[proposal.cpp:21]this is a log\n"
    // Replace the <add> above with the following code at pre-compilation.
    /*
    ([&]{ return print_logs(file_name, file_line, [&](){
        return add(1, 2);
    }); }());
    */
    return0;
}


structmath
{
    [[hookprint_logs]]
    intadd(inta, intb) { return a + b; }
};
intinstead_of_class()
{
    constchar* file_name = __FILE__;
    constint file_line = __LINE__;
    math m;
    m.add(1, 2); // print: "[proposal.cpp:35]this is a log\n"
    // Replace the <m.add> above with the following code at pre-compilation.
    /*
    ([&] { return print_logs(file_name, file_line, [&](){
        return m.add(1,2);
    }); }());
    */
    return0;
}




 "@print_logs" should change to "[[hook print_logs(file_name, file_line)]]", I think.



At 2024-10-27 04:44:50, "Arthur O'Dwyer" <arthur.j.odwyer_at_[hidden]> wrote:

Are you proposing that `m.add(1,2)` should be just syntactic sugar for `print_logs([]m.add, 1, 2)`, where []x.y is N3617's and P0834's (quite nice, but never yet adopted-by-C++) syntactic sugar for `[&](auto&&... args){return m.add(decltype(args)(args)...);}` ? Or is it syntactic sugar for something else? Or is `m.add` itself now really some other kind of entity? or what?
If you are proposing exactly the P0834-style approach, then what happens with something like `(++p)->add(1, 2)`?
Also, how would this (whatever it is) interact with forward-declarations?...
  int f(); // foo.h
  @decorated int f() { return 42; } // foo.cpp


Also, your item (1) mentions inheritance, but I don't see evidence that you've thought about what your feature should do in the presence of inheritance, e.g.
    struct Base { virtual int f(); @decorated virtual int g(); }; // is this OK?
    struct Derived : Base {
      @decorated int f() override; // is this OK?
      int g() override; // what about this?
    };
    Derived d;

    d.g(); // does this call go via the decorator, or not?


Meanwhile, you should probably be aware that in the current year (2024) Brian Bi attempted with P3254 to clear the way for treating `_at_xyz` as a single token — but EWG didn't care for that (at least not at the moment, without any further feature work to build on it). My impression, though, is that he was trying to sell @xyz as a possible future replacement for [[xyz]] (i.e. attributes), rather than as a totally new thing (decorators). So this is a point against your syntax, but only a very minor point IMHO.
https://github.com/cplusplus/papers/issues/1914



–Arthur




On Sat, Oct 26, 2024 at 1:25 PM zys via Std-Proposals <std-proposals_at_[hidden]> wrote:

Dear all:
When I want to execute additional code before functions without changing the source code, there are several approaches I can take:
Use C++ inheritance and override the original function.
Use function hooks at the compile time.
Use lambda functions, etc.
In Python, decorators can assist developers in achieving this and are widely used. Therefore, it is suggested that C++ also adds decorators as a syntactic sugar to help developers quickly implement the execution of extra code before and after functions.
for examples:
#include<stdio.h>
#include<iostream>


template <classFunc, class... Args>
autoprint_logs(Func&&func, Args&&...args)
{
    printf("this is a log\n");
    returnfunc(std::forward<Args>(args)...);
}


@print_logs // Execute print_logs before executing add.
intadd(inta, intb)
{
    return a + b;
}
intcommon()
{
    add(1, 2); // print "this is a log\n"
    // Replace the add above with the following code at pre-compilation.
    // print_logs(add, 1, 2);
    return0;
}


structmath
{
    @print_logs
    intadd(inta, intb) { return a + b; }
};
intinstead_of_lamda()
{
    math m;
    m.add(1, 2); // print "this is a log\n"
    // Replace the add above with the following code at pre-compilation.
    // print_logs([&](int a, int b)
    // { return m.add(a, b); }, 1, 2);
    return0;
}
--
Std-Proposals mailing list
Std-Proposals_at_lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2024-10-27 13:59:32