如何做到这一点?
我没有办法:总有一些东西是无法推断出来的。
不完全是你问的,但我能想象的最好的通过自定义类型特征ttw(用于“模板模板包装器”)
template <template <typename...> class C>
struct ttw
{
template <typename ... Ts>
constexpr ttw (C<Ts...> const &)
{ }
};
使用隐式推导指南,从构造函数接收的类型中提取模板模板并将其用作模板参数。
所以你可以用接收ttw<Templates>的构造函数编写template_pack
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 );
}