Example code could be found below or on compiler explorer. All 3 cases are allowed by gcc while SVariadicTemplate<S>::foo
is rejected by clang and MSVC. Which compiler is correct on this case?
#include <utility>
struct SNonTemplate {
template<template<typename, auto, typename...> typename Template, typename T1, auto V, typename... T>
static void foo(Template<T1, V, T...>) {}
};
template<template<typename, auto> typename Template>
struct STemplate {
template<typename T1, auto V>
static void foo(Template<T1, V>) {}
};
template<template<typename, auto, typename...> typename Template>
struct SVariadicTemplate {
template<typename T1, auto V, typename... T>
static void foo(Template<T1, V, T...>) {}
};
template<typename T, bool b>
struct S {};
static_assert(requires { SNonTemplate::foo(std::declval<S<int, true>>()); });
static_assert(requires { STemplate<S>::foo(std::declval<S<int, true>>()); });
static_assert(requires { SVariadicTemplate<S>::foo(std::declval<S<int, true>>()); }); // error clang/MSVC: too many template arguments for S
I would say IFNDR, according to temp.res#general-6.5
The program is ill-formed, no diagnostic required, if
[..]
(6.5) every valid specialization of a variadic template requires an empty template parameter pack, or
And for SVariadicTemplate<S>
template<typename T1, auto V, typename... T>
static void foo(Template<T1, V, T...>) {}
requires empty pack for T
, and so IFNDR.