I think this is a Clang bug (seen at least with Clang 14.0.5 and recent Clang 16 trunk), but am not completely sure, so wanted to clarify here first:
$ cat test.cc
template<typename, typename> struct Pair;
template<typename...> struct Tuple;
template<typename... Ts> struct A {
template<typename... Us> using B = Tuple<Pair<Ts, Us>...>;
};
template<typename... Ts> struct C {
template<typename... Us> using D = typename A<Ts...>::template B<Us...>;
};
using E = C<int, int>::D<int, int>;
$ clang++ -fsyntax-only test.cc
test.cc:4:30: error: pack expansion contains parameter pack 'Us' that has a different length (2 vs. 1) from outer parameter packs
template<typename... Us> using B = Tuple<Pair<Ts, Us>...>;
^~~~~
test.cc:7:68: note: in instantiation of template type alias 'B' requested here
template<typename... Us> using D = typename A<Ts...>::template B<Us...>;
^
test.cc:9:11: note: in instantiation of template class 'C<int, int>' requested here
using E = C<int, int>::D<int, int>;
^
1 error generated.
(This causes issues now with recent GCC 13 trunk libstdc++ since https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=72886fcc6269531bbf3d9a09b3d64644963bff0d “libstdc++: Implement std::pair/tuple/misc enhancements from P2321R2”,
$ cat test2.cc
#include <map>
#include <tuple>
std::map<std::tuple<int, int>, int> m;
int f(std::tuple<int, int> k) {
return m[k];
}
$ clang++ --gcc-toolchain=gcc/trunk/inst -std=c++2b -fsyntax-only test2.cc
In file included from test2.cc:1:
In file included from gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/map:61:
In file included from gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/bits/stl_map.h:63:
gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/tuple:690:2: error: pack expansion contains parameter pack '_UTypes' that has a different length (1 vs. 2) from outer parameter packs
using __convertible = __and_<is_convertible<_UTypes, _Types>...>;
^~~~~
gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/tuple:852:27: note: in instantiation of template type alias '__convertible' requested here
= _TCC<true>::template __convertible<_Args...>::value;
^
gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/tuple:947:12: note: in instantiation of static data member 'std::tuple<const std::tuple<int, int> &>::__convertible<int &, int &>' requested here
explicit(!__convertible<_UElements&...>)
^
gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/bits/stl_map.h:512:38: note: while substituting deduced template arguments into function template 'tuple' [with _UElements = <int, int>]
std::tuple<const key_type&>(__k),
^
test2.cc:5:13: note: in instantiation of member function 'std::map<std::tuple<int, int>, int>::operator[]' requested here
return m[k];
^
In file included from test2.cc:1:
In file included from gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/map:61:
In file included from gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/bits/stl_map.h:63:
gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/tuple:690:2: error: pack expansion contains parameter pack '_UTypes' that has a different length (1 vs. 2) from outer parameter packs
using __convertible = __and_<is_convertible<_UTypes, _Types>...>;
^~~~~
gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/tuple:852:27: note: in instantiation of template type alias '__convertible' requested here
= _TCC<true>::template __convertible<_Args...>::value;
^
gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/tuple:958:12: note: in instantiation of static data member 'std::tuple<const std::tuple<int, int> &>::__convertible<const int, const int>' requested here
explicit(!__convertible<const _UElements...>)
^
gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/13.0.0/../../../../include/c++/13.0.0/bits/stl_map.h:512:38: note: while substituting deduced template arguments into function template 'tuple' [with _UElements = <int, int>]
std::tuple<const key_type&>(__k),
^
test2.cc:5:13: note: in instantiation of member function 'std::map<std::tuple<int, int>, int>::operator[]' requested here
return m[k];
^
2 errors generated.
)