Рассмотрим следующий сильно шаблонный код:
// 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
Примечание. Любой более простой код, воспроизводящий проблему, приветствуется.