<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/135190>135190</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Clang considers fold expanded constraint ambiguous when it shouldn't be
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
brevzin
</td>
</tr>
</table>
<pre>
Example (from [StackOverflow](https://stackoverflow.com/q/79565469/2069064)):
```cpp
template <class T> inline constexpr bool is_integral_v = false;
template <> inline constexpr bool is_integral_v<int> = true;
template <class T> inline constexpr bool is_floating_point_v = false;
template <> inline constexpr bool is_floating_point_v<double> = true;
template <class T> inline constexpr bool is_arithmetic_v = false;
template <> inline constexpr bool is_arithmetic_v<int> = true;
template <> inline constexpr bool is_arithmetic_v<double> = true;
#if WHICH
template <class T> concept floating_point = is_floating_point_v<T>;
template <class T> concept integral = is_integral_v<T>;
template <class T> concept arithmetic = floating_point<T> or integral<T>;
#else
template <class T> concept arithmetic = is_arithmetic_v<T>;
template <class T> concept floating_point = arithmetic<T> and is_floating_point_v<T>;
#endif
// ------------------------------------
template <arithmetic... Ts>
constexpr int f() {
return 1;
}
template <floating_point... Ts>
constexpr int f() {
return 2;
}
static_assert(f<int>() == 1); // ok
static_assert(f<double>() == 2); // ok
// ------------------------------------
template <class... Ts>
requires(arithmetic<Ts> && ...)
constexpr int g() {
return 1;
}
template <class... Ts>
requires(floating_point<Ts> && ...)
constexpr int g() {
return 2;
}
static_assert(g<int>() == 1); // ok
static_assert(g<double>() == 2); // ok
// ------------------------------------
template <class... Ts>
concept all_arithmetic = (arithmetic<Ts> && ...);
template <class... Ts>
concept all_floating_point = (floating_point<Ts> && ...);
template <class... Ts>
requires all_arithmetic<Ts...>
constexpr int h() {
return 1;
}
template <class... Ts>
requires all_floating_point<Ts...>
constexpr int h() {
return 2;
}
static_assert(h<int>() == 1); // ok
static_assert(h<double>() == 2); // ambiguous with either definition
// ------------------------------------
```
Either way of defining `floating_point` such that it subsumes `arithmetic` leads to `g<double>()` being valid but `h<double>()` being ambiguous, but both should be equivalent.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJysV01zozgQ_TXypSuULAEOBw6JE9fsaQ87VXtMCWhAO7LESMLJ7K-fEsbf9sRxQlGVQ7pfv3791BbCOdloxJwkjyR5mojet8bmhcXV_1JPClP9yp_fxLJTCITd19YsgSSP_3hR_vh7hbZW5pUkT4Tdt953jvAHwhaELVwIMGNAVJolYYufhC1mWZImcZoRtmA0zWgaE5aFlz8QOrwpXb9l1xH64HHZKeERCJ-XSjgH3wl_BqmV1Ail0c7jW2ehMEaBdC9Se2ysUC8rIPwJaqEcEv54hHQlBOFzqX0IDlje9iPUDbxqZYSXunnpjNT-E-yOgQifV6YvFH4JTWGlb5foZfkJivsglyS8FewPvRLGZQ3_fvtr_u1y56XRJXYeDmUcwM6LG7JOKZ9B3Nhmg3Vgo6tRdu2u5T8gNAKBsdtqB9iEcQzj-miVU5mv5ntGxx3Uhq_Q1bvqBu66kvVmlmGJwN0Vz6nRdwSiKILvLtSgDztrBaI1YfeEZUBmoTiARd9bDdORzOzpFPaQ_oeh2RG08yKoLZxD68Nq3R6VTT5_CnJOh-34CKMk5seF3O3JOExnY_pB_mcVHoywrwBY_NlLi46w-8P5u-GsspSwFKIoCmyOBWs-PotTAvsMTk_N7SzeG1vzibE1N4ztqye3XQlKvRythWtmefGH5lKNMwvj2oldVWvrg6OOBswAdObEtl9qwDNt3lD8Pd-17_guPH_yXnu998SykE1vegev0reA0rdoocJaauml0TfZcnPNWyc_rzFfxS8w9QitGyApPRIypeD6sgXfCg_Sg-sL1y_RhdC9YacUFIrKgTfhP2cOWggpMBRZCSUrKHofIs_IsovcCkHYfEgojG_BtaZXFRQIwQAroVD7CCZVzquMZ2KC-XQWxyxLKU8mbZ6kSVVSSrOCz5KkzjjDmrOqSqoZK_mUTWTOKEtoPKXTOKY8iUSWxoLHZZXVouasJDHFpZAqUmq1jIxtJtK5HvMpT6YZnShRoHLDhZ6xUgndEMbC3d7mIeGu6BtHYqqk824H4aVXmM9D-HALkxVaB7VRFeBbJ3SF1fp2ZkVw7Z4nWtTDJAYZNGEzDwVOeqvyw0-CRvq2L8ZvgVB3_HPXWfMflp6wxdCHI2wxtrLK2e8AAAD__8Nt1gc">