jupyter-xeus / xeus-cling

Jupyter kernel for the C++ programming language
BSD 3-Clause "New" or "Revised" License
3.08k stars 297 forks source link

C++17 kernel not working for folding expressions #434

Open mmoelle1 opened 2 years ago

mmoelle1 commented 2 years ago

I tried several version of xeus-cling (including 0.9 which is reported to work with C++17) on the following code (taken from https://quuxplusone.github.io/blog/2020/10/12/fold-a-function/):

#define FWD(x) static_cast<decltype(x)>(x)
#define MOVE(x) static_cast<decltype(x)&&>(x)

template<class F, class TRR>
struct Folder {
    const F& foo_;
    TRR value_;

    template<class U>
    constexpr auto operator+(Folder<F, U>&& rhs) && -> decltype(auto) {
        using R = decltype(foo_(FWD(value_), FWD(rhs.value_)));
        return Folder<F, R>{foo_, foo_(FWD(value_), FWD(rhs.value_))};
    }
};

template<class F>
constexpr auto left_fold(F foo) {
    return [foo = MOVE(foo)](auto&&... args) -> decltype(auto) {
        return (... + Folder<F, decltype(args)>{foo, FWD(args)}).value_;
    };
}

template<class F>
constexpr auto right_fold(F foo) {
    return [foo = MOVE(foo)](auto&&... args) -> decltype(auto) {
        return (Folder<F, decltype(args)>{foo, FWD(args)} + ...).value_;
    };
}

Xeus-cling terminates with the following error message

input_line_7:16:65: error: expected ';' after return statement
        return (... + Folder<F, decltype(args)>{foo, FWD(args)}).value_;
                                                                ^
                                                                ;
Interpreter Error: 

Changing the above code to

template<class F>
constexpr auto left_fold(F foo) {
    return [foo = MOVE(foo)](auto&&... args) -> decltype(auto) {
        auto t = (... + Folder<F, decltype(args)>{foo, FWD(args)});
        return t.value_;
    };
}

seems to work. It seems to be a bug in the interpreter. Or isn't the original version valid C++ code?

Best regards, Matthias

adah1972 commented 1 year ago

This seems fixed already? It works for me now.

Anyway, I reproduced the problem on an older version. It seems a parser issue, and there is an easy workaround: just change return (... + Folder<F, decltype(args)>{foo, FWD(args)}).value_; to return ((... + Folder<F, decltype(args)>{foo, FWD(args)})).value_;.