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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With