Issue 135190
Summary Clang considers fold expanded constraint ambiguous when it shouldn't be
Labels clang
Assignees
Reporter brevzin
    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. 
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to