I think I hit a template type deduction bug in all the compilers, but before reporting it I want to be sure I did not miss something.
Consider an example:
#include <utility>
template <std::size_t... I, typename... T>
void foo(std::index_sequence<I...>, decltype(I)..., T...) {}
int main()
{
foo(std::make_index_sequence<3>{}, 1, 2, 3, 4, 5);
}
decltype(I)
is used here to make MWE shorter.
error: too few arguments to function
error: no matching function for call to 'foo'
error C3543: 'unknown-type': does not contain a parameter pack
I don't understand why it fails to deduct T
, especially because it works if I replace parameter pack with varargs (except MSVC, it has ICE again).
template <std::size_t... I>
void foo(std::index_sequence<I...>, decltype(I)..., ...) {}
There are many other ways to make what I want, but this is the shortest way and I do not see any reasons it should fail.
Update: The know valid example with substitution on deducible is:
template <typename T>
struct type_identity
{ using type = T; };
template <typename T, typename... U>
void foo(T, typename type_identity<T>::type, U...) {}
int main()
{
foo(1, 2, 3, 4, 5);
}
Update #2 The modified version of the original example does not crash Clang, but a note on the error is strange note: candidate template ignored: deduced conflicting types for parameter 'T' (<int, int, int> vs. <>)
#include <utility>
template <typename T>
struct type_identity
{ using type = T; };
template <typename...>
struct type_pack {};
template <typename... T, typename... U>
void foo(type_pack<T...>, typename type_identity<T>::type..., U...) {}
int main()
{
foo(type_pack<int, int, int>{}, 1, 2, 3, 4, 5);
}
I think your code is ill-formed by the standard, but an argument could be made that the standard should be changed to make it well-formed.
The template argument deduction process is described in the standard as follows:
Thus, the procedure is substitution-deduction-substitution; there is no subsequent deduction after the substitution of deduced arguments. Further support for this view is provided by [temp.deduct]/6:
At certain points in the template argument deduction process it is necessary to take a function type that makes use of template parameters and replace those template parameters with the corresponding template arguments. This is done at the beginning of template argument deduction when any explicitly specified template arguments are substituted into the function type, and again at the end of template argument deduction when any template arguments that were deduced or obtained from default arguments are substituted.
Your example is ill-formed because it requires deduction then substitution then deduction: T...
cannot be deduced unless I...
is first both deduced and substituted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With