<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/129912>129912</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Incorrect Clang compilation error in non-taken if-constexpr branch within template lambda
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
mikebentley15
</td>
</tr>
</table>
<pre>
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.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzUV01v4zgS_TX0pRBDImPLPvjgKB-YwwAL7AA5BjRVtriRSA1ZSjp92N--KEq25bR70YduoEcw4phFFV-9Kj4WdYz24BA3YnEnFvcz3VPtw6a1r7hDRw1-5IvZzlcfmydf7XxDQm2hJuqiUFshH4V8PAyGuQ8HIR-_Cvn4_PT87L8-5X-LbCuy7V81QjTodLAebIS9tqH5gEhBuwMCeQjYBV_1BucAf5CQRQTjq2Qy3lWWrHe6aT7gPegONBjdNHrXILxbqkFD21P66QMbvYsEjW53lZ4D8Opimdn9YMAvXRDLDHZBO1MD1ZrARidkQUD6FR0Y3UeMQDWC8W1nG83LM5a9ts18iOnftu0au7dYJaRMRhoXy2z4GCHv-JNthVTWmaavEIQqTaTKeqEevrFYHymgbq_Z6KPDFwraUrxm7sk2lj5GU7aNFHpDUHLAz0F3PFrcieJeqLuz-c-BtSsTRLbVPfmRxDRBrtLIkXkh13Aj1ANUaBpGN04Qcj36yrYAMCYjvVqh8UGTDyDUPXC9yeXJ3eJ-jNLpFoFX_IudqgchV7zW2SM_02SCkKtIFWdAbW18ibrFlzehynP0srz0-NkdPwGpD45hGd1RH7Aqj0XGcE8rtP6NY53wwNivgTw-p1e7nmKaKSfQJHtIpMPnhQevo3HynNI0GQBsIh4B_IxYjltqdHkliGn5TMP49PzfqK6FMv66MI0RnUpoTth2jSYE32EaObotp7CO5TNWdfItsq11BK22bjRO63VaqVgxXWy42AdMq-8d4VDI2VXOzoQZ3xPvUaFKSKlPr7KMCinPBhaLs9vjbLEoHX-pu8THlOMTyM9lMnKVXQR9lKWjIg8y3MSkoJ-ki_9XZfR9MGm_qG1eHP8AhuATeueh1WRq6w6w751JIrn3IUkEq6Xf_QcNgd8D72sQshjE4LTLTxQF5Ep8CbjHgI4XLYVcDaSDTuxN0Sgp1FZmacfJ5TAm1HZQoYL1QL_q83o_5krIYqgFAMgLEEX5A_uRZ4nFw38vnyv8LYTaLtVAG_FpAe-1bRBiv4tkqSdm0TryoMdiA9Y2jJFZrTHgiGyR1vyVwjXGdCUIxr_Mf0IQ6hTErzgevhtASvZ6it86sC6SdmSHQ97vz7V8kpjYobG6sV-HOUIWEz340VJNWAsI-HePkaXlzIeSF0n9HcUGLhB-n12ZTek12lW2YgpPpDpP8GZTThOogmobmRgdDn2LjqDW8Z8kGLKEXU_QItW-4u6WI2x1eE2doYt0kePfP7fTPiOlOR8kHw7oMJ033AGXqTHGMKoPMkTIvz1ovIOy0e4A-WqezzPQrgLeWqF3r6lx47QOR4pcp2bdRnj34TVyj0dD635SBu7bx8yMRPPpZR3o02atzqUm5ArnhzlniKsFLA3iJJbZ5PBfDqAsDcsOMP78ANOHwOXIozr43qXkkh980fVLhe8p2grTmfct9vHq8FSWkGfzW_ZndDdcXPbjXYMllLcE4Bfddg2O7_wLQ627OJhshIBDsByOVHmuirWcz6qNqtZqrWe4yYvbXGZZoeSs3qyyVa5xleW3uFqpZbXLb43SxizlWuZyv5jZjczkIlPZIl8tZC7nu0WxNItVplSeG4OZuM2w5dtP07y1fNOb2Rh73ORyvc7lrNE7bGK6Q0ppOOGp5O5nYcMv3Oz6QxS3WWMjxbMLstTg5g9nfAjcKQyVMr1zDZVnWTbczXA7s_ubc-s_XuLGKjgJ9lAjsz40m09XVUt1v5sb3wr5yDjGr5sueG5WhHxMcUUhH8fQ3jbyfwEAAP__8vOErA">