Clang considers fold expanded constraint ambiguous when it shouldn't be (original) (raw)
Example (from StackOverflow) using C++26's ability to order constraints involving fold expressions (P2963):
template inline constexpr bool is_integral_v = false; template <> inline constexpr bool is_integral_v = true;
template inline constexpr bool is_floating_point_v = false; template <> inline constexpr bool is_floating_point_v = true;
template inline constexpr bool is_arithmetic_v = false; template <> inline constexpr bool is_arithmetic_v = true; template <> inline constexpr bool is_arithmetic_v = true;
#if WHICH template concept floating_point = is_floating_point_v; template concept integral = is_integral_v; template concept arithmetic = floating_point or integral; #else template concept arithmetic = is_arithmetic_v; template concept floating_point = arithmetic and is_floating_point_v; #endif
// ------------------------------------
template <arithmetic... Ts> constexpr int f() { return 1; }
template <floating_point... Ts> constexpr int f() { return 2; }
static_assert(f() == 1); // ok static_assert(f() == 2); // ok
// ------------------------------------
template <class... Ts> requires(arithmetic && ...) constexpr int g() { return 1; }
template <class... Ts> requires(floating_point && ...) constexpr int g() { return 2; }
static_assert(g() == 1); // ok static_assert(g() == 2); // ok
// ------------------------------------
template <class... Ts> concept all_arithmetic = (arithmetic && ...);
template <class... Ts> concept all_floating_point = (floating_point && ...);
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() == 1); // ok static_assert(h() == 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.