[openmethod] Joaquin's syntax suggestion

During the review, Joaquin suggested changing the syntax for declaring and overriding methods, from: BOOST_OPENMETHOD(poke, (virtual_ptr<Animal>, std::ostream&), void); BOOST_OPENMETHOD_OVERRIDE( poke, (virtual_ptr<Bulldog> dog, std::ostream& os), void) { ... } to: BOOST_OPENMETHOD(poke, void(virtual_ptr<Animal>, std::ostream&)); BOOST_OPENMETHOD_OVERRIDE( poke, void(virtual_ptr<Bulldog> dog, std::ostream& os)) { ... } The difficulty with this is that the macros generate several constructs using the method name, formal parameter list and return type. Steven suggested a trick to implement a similar syntax, using trailing return types: BOOST_OPENMETHOD(poke, (virtual_ptr<Animal>, std::ostream&)->void); BOOST_OPENMETHOD_OVERRIDE( poke, (virtual_ptr<Bulldog> dog, std::ostream& os)->void) { ... } but I am not 100% sure if he actually _supports_ the change. @Steven, do you? Personally, I like the above because it simplifies the macros. But it has a couple of drawbacks. 1. `(virtual_ptr<Animal>, std::ostream&)->void` is not legal C++, `auto (virtual_ptr<Animal>, std::ostream&)->void` is. Isn't this going to cause confusion? 2. Count on MSVC to spoil things. If the return type is explicitly derived from a template, MSVC errors on it. Here is a reduction: #include <string> #include <tuple> template<typename> struct test{}; using foo = test<auto (int)->std::string>; using bar = test<auto (int)->std::tuple<int>>; // MSVC fails on this using baz = test<auto (int)->decltype(std::tuple<int>())>; // workaround Compiler Explorer: https://godbolt.org/z/MrbdYbW9Y It looks like a parser bug, I reported it. To all those who did _not_ suggest this change, if you oppose it, please let me know. J-L

On Sun, May 25, 2025 at 12:37 AM Jean-Louis Leroy via Boost < boost@lists.boost.org> wrote:
As I often use GMock I would prefer same pattern here, return type, name, args this is example from GMock docs(ignore override): MOCK_METHOD(void, Forward, (int distance), (override)); Benefit is that trailing return type is not commonly used in codebases where I worked, and downside is that name of method is not first... so when you have 20 methods one after another first column is return types, and name of fn is second column, so it is a bit less readable. I am not a fan of: poke, void(virtual_ptr<Animal>: since afaik there is no C++ syntax that nas name, return type, arguments ordering. But to be honest I would not consider either of the options you suggested bad so no strong pro or against votes from me. :)

Same as YOMM2: declare_method(void, poke, (virtual_<Animal&>, std::ostream&)); define_method(void, poke, (Dog& dog, std::ostream& os)) { os << "bark"; } So why did I change it to this? BOOST_OPENMETHOD(poke, (virtual_ptr<Animal>, std::ostream&), void); BOOST_OPENMETHOD_OVERRIDE( poke, (virtual_ptr<Dog> dog, std::ostream& os), void) { os << "bark"; } That's because the YOMM2 syntax does not work well with return types that contain commas, like `std::tuple<int, float>`, forcing you to use tricks like typedefs or `BOOST_IDENTITY_TYPE`. The new syntax requires that the method name be an identifier, so we know for sure that the first macro argument is the entire thing, not a bit of it (e.g., not `std::tuple<int`). The second is wrapped in parentheses. That always gives a single argument. The return type and optional registry (if not using the default) are simply `__VA_ARGS__`. Maybe the return type is split into several macro arguments, but it doesn't matter, because it is passed as a whole to the `method` template.
It is a valid function type, as in `std::function<int(char, float)>`. To sum up: void(virtual_ptr<Animal>) : valid function type auto(virtual_ptr<Animal>) -> void : same valid function type (virtual_ptr<Animal>) -> void : NOT valid J-L

On Sun, May 25, 2025 at 11:10 PM Jean-Louis Leroy via Boost < boost@lists.boost.org> wrote:
This is actually strong argument, comma thing is quite obnoxious with GMock, not to mention that last time I hit it compiler error message was useless. So you have convinced me. :)
It is a valid function type, as in `std::function<int(char, float)>`
I meant when you declare function in C++ you can do: auto my_sum(int, int) -> int int my_sum(int, int) but you can not do: my_sum int(int, int)
participants (2)
-
Ivan Matek
-
Jean-Louis Leroy