Issue |
129912
|
Summary |
Incorrect Clang compilation error in non-taken if-constexpr branch within template lambda
|
Labels |
clang
|
Assignees |
|
Reporter |
mikebentley15
|
Godbolt: https://godbolt.org/z/WGWWozG1q
The scenario is fairly strange to reproduce. It's code to conditionally wrap a callable with a mutable or a const lambda. The `if constexpr` branch that isn't taken causes the compilation to fail.
Simplified code:
```c++
#include <cstdio>
#include <iostream>
#include <type_traits>
#include <utility>
struct ConstWrap
{};
struct MutableWrap
{};
auto lambdaWrap(auto callable) -> decltype(auto)
{
const auto decorator = [&callable]<typename WrapType>() {
if constexpr (std::is_same_v<ConstWrap, WrapType>) {
return [capturedCallable = std::move(callable)]() {
std::puts("ConstWrap");
capturedCallable();
};
} else {
return [capturedCallable = std::move(callable)]() mutable {
std::puts("MutableWrap");
capturedCallable();
};
}
};
return decorator.template operator()<MutableWrap>();
}
int main()
{
auto decorated =
lambdaWrap([counter = 0]() mutable { std::cout << "Counter: " << ++counter << "\n"; });
decorated();
return 0;
}
```
This fails with
```
<source>:17:17: error: no matching function for call to object of type 'const typename std::remove_reference<(lambda at <source>:32:20) &>::type' (aka 'const (lambda at <source>:32:20)')
17 | capturedCallable();
| ^~~~~~~~~~~~~~~~
<source>:15:63: note: while substituting into a lambda _expression_ here
15 | return [capturedCallable = std::move(callable)]() {
| ^
<source>:13:61: note: while substituting into a lambda _expression_ here
13 | const auto decorator = [&callable]<typename WrapType>() {
| ^
<source>:32:9: note: in instantiation of function template specialization 'lambdaWrap<(lambda at <source>:32:20)>' requested here
32 | lambdaWrap([counter = 0]() mutable { std::cout << "Counter: " << ++counter << "\n"; });
| ^
<source>:32:20: note: candidate function not viable: 'this' argument has type 'const typename std::remove_reference<(lambda at <source>:32:20) &>::type' (aka 'const (lambda at <source>:32:20)'), but method is not marked const
32 | lambdaWrap([counter = 0]() mutable { std::cout << "Counter: " << ++counter << "\n"; });
| ^
1 error generated.
Compiler returned: 1
```
on Clang 18.1.0 and on trunk (same error). This works if the `decorator` lambda is not within a templated function (e.g., move it into `main()` and it works). My current workaround is to move the `if constexpr` outside of the `decorator`.
GCC 10.4 is capable of compiling this example.
Perhaps this is related to #113792.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs