Как заставить это работать?
Я не вижу пути: есть что-то, что не может быть выведено.
Не совсем то, что вы просили, но лучшее, что я могу представить, это пройти через пользовательские черты типа ttw
(для "template-template-wrapper")
template <template <typename...> class C>
struct ttw
{
template <typename ... Ts>
constexpr ttw (C<Ts...> const &)
{ }
};
что, используя неявные руководства по выводам, извлекает шаблон-шаблон из типа, полученного из конструктора, и использует его в качестве параметра шаблона.
Таким образом, вы можете написать template_pack
с помощью конструктора, который получает ttw<Templates>
template <template <typename...> class... Templates>
struct template_pack
{
constexpr template_pack (ttw<Templates> const & ...)
{ }
};
, который вы можете использовать следующим образом (опять же: через неявные инструкции по выводу)
template_pack tp1 {ttw{std::vector<int>{}},
ttw{std::set<long>{}},
ttw{std::map<char, short>{}}};
Проблема в том, что необходимо явно обернуть аргументы в ttw{}
, потому что, для примера, std::vector<int>
можно преобразовать в ttw<std::vector>
, но не ttw<std::vector>
. Таким образом, передавая std::vector{}
вместо ttw{std::vector{}}
, мы имеем обычную задачу типа "курица / яйцо" типа, который не может быть выведен, потому что для его вывода требуется преобразование, которое требует знания типа, который мы хотим вывести.
Очевидно, что вы можете требовать явного ttw
упаковывания для определенной make_template_pack()
функции
template <typename ... Ts>
constexpr auto make_template_pack (Ts && ... ts)
{ return template_pack{ttw{std::forward<Ts>(ts)}...}; }
Ниже приведен полный пример компиляции
#include <map>
#include <set>
#include <vector>
#include <type_traits>
template <template <typename...> class C>
struct ttw
{
template <typename ... Ts>
constexpr ttw (C<Ts...> const &)
{ }
};
template <template <typename...> class... Templates>
struct template_pack
{
constexpr template_pack (ttw<Templates> const & ...)
{ }
};
template <typename ... Ts>
constexpr auto make_template_pack (Ts && ... ts)
{ return template_pack{ttw{std::forward<Ts>(ts)}...}; }
int main ()
{
template_pack tp1 {ttw{std::vector<int>{}},
ttw{std::set<long>{}},
ttw{std::map<char, short>{}}};
auto tp2 { make_template_pack(std::vector<long>{},
std::set<int>{},
std::map<char, short>{}) };
using t0 = template_pack<std::vector, std::set, std::map>;
using t1 = decltype(tp1);
using t2 = decltype(tp2);
static_assert( std::is_same<t0, t1>::value );
static_assert( std::is_same<t0, t2>::value );
}