jll63 / yomm2

Fast, orthogonal, open multi-methods. Solve the Expression Problem in C++17.
Boost Software License 1.0
343 stars 18 forks source link

Comma inside declare_method #13

Closed derpda closed 4 years ago

derpda commented 4 years ago

When I try to use a tuple (or anything including a comma in it's definition) inside declare_method, the macro seems unable to parse the arguments.

Minimal example:

#include "yorel/yomm2/cute.hpp"
using yorel::yomm2::virtual_;

#include <tuple>

class Matrix;

declare_method(void, test, (virtual_<const Matrix&>, std::tuple<int, int>))

The errors are something like error: template argument 1 is invalid and error: ‘yorel::yomm2::detail::virtual_arg_t’ is not a type.

I still do not understand the library well enough to understand why exactly this is the case or if it is fixable, but I would love to get some feedback on this!

jll63 commented 4 years ago

Well, that's a problem with commas inside macro arguments. Unless they are wrapped inside parentheses, they cause trouble. And angle brackets don't count as parentheses.

A workaround is to use a synonym (e.g. using int_pair = tuple<int, int>). Another is to express the type in a way that puts parentheses around the template arguments, e.g.:

#include <string>

using yorel::yomm2::virtual_;
using std::cout;

#include <tuple>

struct Matrix {
    virtual ~Matrix() {}
};

register_class(Matrix);

declare_method(
    int, test, (virtual_<const Matrix&>, decltype(std::tuple<int, int>())));

define_method(
    int, test, (const Matrix&, decltype(std::tuple<int, int>()) ints)) {
    return std::get<0>(ints) + std::get<1>(ints);
}

int main() {
    yorel::yomm2::update_methods();
    const Matrix m;
    cout << test(m, std::make_tuple(1, 2)) << "\n"; // outputs: 3
    return 0;
}

I could introduce a macro to wrap this, but I'm not sure it is necessary. I should also mention this issue (and the workarounds) in the documentation. What do you think?

FWIW the D implementation doesn't have that sort of problem ;-)

derpda commented 4 years ago

Yeah I've been using that workaround and while it works fine, I just wasn't sure if this was an oversight and could easily be fixed or not. I hadn't thought of using decltype inside the definition though, maybe that's slightly better!

Since it apparently can't easily be fixed, mentioning it in the readme might indeed be good though! The error messages are naturally somewhat cryptic.

If only writing in D was an option for me :D

Thank you as always for your quick response! :)

jll63 commented 4 years ago

Documented in dca2c579b0d468749fa201b615fb1f64acc84f92