模板模板,可变参数模板和演绎指南:编译器错误?

时间:2019-05-06 08:33:38

标签: c++ c++17 template-deduction compiler-bug template-templates

考虑以下高度模板化的代码:

// 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 89,但不适用于clang。但是我不知道这是否是有效的C ++。由于它适用于gcc而不适用于clang,因此毫无疑问,一个是正确的,但另一个则不正确。哪个是对的?

clang返回的错误是:

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

注意:欢迎使用任何更简单的代码来重现该问题。

0 个答案:

没有答案