Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic lambda, inheritance and trailing return type: is this valid code?

I was trying to reply to another answer and I found some difficulties while playing with lambdas and inheritance. Consider the following, minimal example:

template<typename Func>
struct Base: Func {
    Base(Func func): Func{func} {}

    template<typename... Args>
    auto operator()(Args... args)
    -> decltype(Func::operator()(args...), void()) {
        Func::operator()(args...);
    }
};

int main() {
    auto l = [](auto &&) {};
    Base<decltype(l)> mixin{l};
    mixin(0);
}

GCC 6.1 compiles it, clang 4.0 crashes (see https://godbolt.org/z/6Gz5s66h5). Note that both compile just fine using the following definition:

auto l = [](int) {};

Is this valid code or I'm doing something that is not allowed by the standard?


I've reported this as LLVM bug 31356, though I'd still like to know whether my code is correct.

like image 333
skypjack Avatar asked May 04 '26 13:05

skypjack


1 Answers

The bug report you've opened has been resolved in clang 14. Note that if a compiler crashes, this is always a bug, and not your fault.

Is this valid code or I'm doing something that is not allowed by the standard?

Yes, it is valid C++14 code, and more recent versions of clang allow it too. The only difference between [](auto &&) {}; and [](int) {} is that one lambda has a call operator that's a member function template, not just a member function.

That should not prevent you from inheriting from the lambda's closure type, or anything else you're doing in your code.

Workaround

The ICE seems to occur when parsing -> decltype(Func::operator()(args...), void()). You could instead write:

template<typename... Args>
auto operator()(Args... args) -> decltype(std::declval<Func&>()(args...), void())
{
    Func::operator()(args...);
}

See live example at Compiler Explorer using clang 13

like image 150
Jan Schultke Avatar answered May 06 '26 03:05

Jan Schultke



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!