【发布时间】:2017-10-18 14:43:53
【问题描述】:
厌倦了“统一初始化”不是很统一,我决定编写一个通用的 construct() 包装器,如果类型是聚合则使用聚合初始化,否则直接初始化:
template <class T, class... Args,
std::enable_if_t<std::is_aggregate_v<T>, int> = 0>
constexpr auto construct(Args&&... args)
-> decltype(T{std::forward<Args>(args)...})
{
return T{std::forward<Args>(args)...};
}
template <class T, class... Args>
constexpr auto construct(Args&&... args)
-> decltype(T(std::forward<Args>(args)...))
{
return T(std::forward<Args>(args)...);
}
这很好用:
template <class T, class U>
struct my_pair { T first; U second; };
auto p = construct<my_pair<int, float>>(1, 3.14f);
auto v = construct<std::vector<int>>(5, 0);
我想扩展它以使用构造函数的模板参数推导。所以我添加了另一对重载:
template <template <class...> class T, // <-- (1)
class... Args,
class A = decltype(T{std::declval<Args>()...}),
std::enable_if_t<std::is_aggregate_v<A>, int> = 0>
constexpr auto construct(Args&&... args)
-> decltype(T{std::forward<Args>(args)...})
{
return T{std::forward<Args>(args)...};
}
template <template <class...> class T, // <-- (1)
class... Args>
constexpr auto construct(Args&&... args)
-> decltype(T(std::forward<Args>(args)...))
{
return T(std::forward<Args>(args)...);
}
也许令人惊讶(至少对我而言),这适用于简单的情况:
// deduction guide for my_pair
template <class T, class U> my_pair(T&&, U&&) -> my_pair<T, U>;
auto p = construct<my_pair>(1, 3.14f); // my_pair<int, float>
auto v = construct<std::vector>(5, 0); // vector of 5 ints
不幸的是,在尝试调用时失败了
auto a = construct<std::array>(1, 2, 3); // No matching call to construct()
因为std::array有一个非类型模板参数,所以与(1)处的template <class...> class T模板模板参数不匹配。
所以我的问题是,有没有办法在 (1) 处制定参数,以便它可以接受 any 类模板名称,而不管其类型(类型或非类型)如何模板参数?
【问题讨论】:
标签: c++ templates c++17 template-templates