Лямбда со списком параметров шаблона с использованием C ++ 20 требует предложений, которые нельзя использовать в постоянном выражении

2020-08-01 c++ lambda c++20 c++-concepts

В функции шаблона f я определяю лямбду со списком параметров шаблона, который можно использовать if constexpr для определения того, является ли тип U std::vector :

template <typename T>
void f(T t) {
  auto g = []<typename U>(U u) {
    if constexpr (requires { std::same_as<U, std::vector<typename U::value_type>>; }) {
      if constexpr (std::same_as<U, std::vector<typename U::value_type>>) {
        // deal with std::vector<U::value_type>
      }
    }
    else {
      // deal with other type
    }
  };
  g(t);
}

Но когда я вызываю f в main функции:

int main()
{
  f(std::vector<int>{});
}

Компилятор GCC-10 выдает ошибку:

<source>:19:23:   required from here
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/concepts:57:15:   required for the satisfaction of '__same_as<_Tp, _Up>' [with _Tp = U; _Up = std::vector<typename U::value_type, std::allocator<typename U::value_type> >]
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/concepts:57:32: error: the value of 'std::is_same_v<U, std::vector<typename U::value_type, std::allocator<typename U::value_type> > >' is not usable in a constant expression
   57 |       concept __same_as = std::is_same_v<_Tp, _Up>;
      |                           ~~~~~^~~~~~~~~~~~~~~~~~~
In file included from /opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/concepts:44,
                 from <source>:1:
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/type_traits:3182:25: note: 'std::is_same_v<U, std::vector<typename U::value_type, std::allocator<typename U::value_type> > >' used in its own initializer
 3182 |   inline constexpr bool is_same_v = _GLIBCXX_BUILTIN_IS_SAME_AS(_Tp, _Up);
      |                         ^~~~~~~~~ 

Мне это кажется странным, поскольку тип U можно вывести во время компиляции. Это ошибка GCC-10? или есть проблема в приведенном выше коде?

Что еще более странно, когда я меняю происхождение требует предложений во вложенные требования :

template <typename T>
void f(T t) {
  auto g = []<typename U>(U u) {
    if constexpr (requires { requires std::same_as<U, std::vector<typename U::value_type>>; }) {
      // deal with std::vector<U::value_type>
    }
    else {
      // deal with other type
    }
  };
  g(t);
}

GCC возникает внутренняя ошибка компилятора :

<source>:19:23:   required from here
<source>:7:39: internal compiler error: in dependent_type_p, at cp/pt.c:26400
    7 |     if constexpr (requires { requires std::same_as<U, std::vector<typename U::value_type>>; }) {
      |                              ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Please submit a full bug report,
with preprocessed source if appropriate.

и когда я меняю шаблонную функцию f на не шаблонную функцию:

void f(std::vector<int> t) {
  auto g = []<typename U>(U u) {
    if constexpr (requires { requires std::same_as<U, std::vector<typename U::value_type>>; }) {
      // deal with std::vector<U::value_type>
    }
    else {
      // deal with other type
    }
  };
  g(t);
}

Он будет правильно скомпилирован, и все три примера компилируются с Clang .

Answers

Related