Шаблон-шаблон, шаблон переменной и руководство по выводу: ошибка компилятора? - PullRequest
5 голосов
/ 06 мая 2019

Рассмотрим следующий сильно шаблонный код:

// Preamble
#include <list>
#include <deque>
#include <vector>
#include <iostream>
#include <type_traits>

// Rebind template template type traits
template <class> struct rebind_template_template;
template <template <class...> class Template, class... Types>
struct rebind_template_template<Template<Types...>> {
    template <class... Args>
    using type = Template<Args...>;
};

// Rebind template parameters type traits
template <class> struct rebind_template_parameters;
template <template <class...> class Template, class... Types>
struct rebind_template_parameters<Template<Types...>> {
    template <template <class...> class Arg>
    using type = Arg<Types...>;
};

// Template pack
template <template <class...> class... Templates>
class template_pack
{
    private:
    template <class... Args>
    using if_constructible_t = std::void_t<
        typename rebind_template_parameters<Args>::template type<Templates>...
    >;

    public:
    template <class... Args, class = if_constructible_t<Args...>>
    constexpr template_pack(const Args&...) noexcept {}
};

// Class template argument deduction guide
template <class... Args>
template_pack(const Args&...) -> template_pack<
    rebind_template_template<Args>::template type...
>;

// Pretty-printing
template <class Arg>
void print() {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

// Main
int main(int argc, char* argv[])
{
    template_pack pack(std::list<int>{}, std::deque<int>{}, std::vector<int>{});
    print<decltype(pack)>();
    return 0;
}

Что это делает, так это то, что он выводит пакет шаблонов из своих аргументов. Он работает на gcc 8 и 9, но не на clang. Но я понятия не имею, является ли это действительным C ++. Тем не менее, поскольку он работает на gcc, но не на clang, одно верно, а другое нет. Какой из них прав?

Ошибка, возвращаемая clang:

error: pack expansion contains parameter pack 'Args' 
that has a different length (3 vs. 1) from outer parameter packs

Примечание. Любой более простой код, воспроизводящий проблему, приветствуется.

...