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.