c++language-lawyervariadic-templatestemplate-argument-deduction

template argument deduction with variadic template template


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

Solution

  • 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.