C++ 通用模板参数

C++ 通用模板参数,c++,templates,c++17,template-templates,C++,Templates,C++17,Template Templates,受够了“统一初始化”不是很统一,我决定编写一个通用的construct()包装器,如果类型是聚合,则使用聚合初始化,否则直接初始化: template <class T, class... Args, std::enable_if_t<std::is_aggregate_v<T>, int> = 0> constexpr auto construct(Args&&... args) -> decltype(T{

受够了“统一初始化”不是很统一,我决定编写一个通用的
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)...);
}
模板
constexpr自动构造(Args&&…Args)
->decltype(T{std::forward(args)…})
{
返回T{std::forward(args)…};
}
模板
constexpr自动构造(Args&&…Args)
->decltype(T(std::forward(args)…)
{
返回T(标准:正向(参数)…);
}
这很有效:

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);
模板
结构my_对{T first;U second;};
自动p=构造(1,3.14f);
自动v=构造(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)...);
}
模板decltype(T{std::forward(args)…})
{
返回T{std::forward(args)…};
}
模板decltype(T(std::forward(args)…)
{
返回T(标准:正向(参数)…);
}
也许令人惊讶的是(至少对我来说),这适用于简单的情况:

// 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
//我的\u对演绎指南
模板my_对(T&&,U&)->my_对;
自动p=构造(1,3.14f);//我的鞋
自动v=构造(5,0);//5整数向量
但不幸的是,当尝试调用

auto a = construct<std::array>(1, 2, 3); // No matching call to construct()
autoa=construct(1,2,3);//没有对construct()的匹配调用
因为
std::array
具有非类型模板参数,因此它与(1)处的
template class t
template模板参数不匹配


因此,我的问题是,是否有一种方法来表述(1)处的参数,使其可以接受任何类模板名称,而不管其模板参数的类型(类型或非类型)?

不幸的是,如果不重复代码,就没有正确的方法。C++17中新增的“
auto
as-template参数”仅支持非类型模板参数

我认为唯一可行的方法是使用代码生成器生成一定数量的
auto
class
排列。例如

template <
    template <class, auto...> class T,
    class... Args>
constexpr auto construct(Args&&... args) // ...

template <
    template <class, auto, class...> class T,
    class... Args>
constexpr auto construct(Args&&... args) // ...

template <
    template <auto, class, auto...> class T,
    class... Args>
constexpr auto construct(Args&&... args) // ...

template <
    template <auto, class, auto, class...> class T,
    class... Args>
constexpr auto construct(Args&&... args) // ...

template <
    template <auto, class, auto, class, auto...> class T,
    class... Args>
constexpr auto construct(Args&&... args) // ...

// and so on...
模板<
模板类T,
类。。。Args>
constexpr自动构造(Args&…Args)/。。。
模板<
模板类T,
类。。。Args>
constexpr自动构造(Args&…Args)/。。。
模板<
模板


听起来你对提案有个好主意…

模板似乎足够了?:)可能涵盖了所有实际案例(
std::array
std::integer_sequence
)。@Barry:这在99%的案例中可能已经足够好了,但是如果我分发一个包含
construct
的库,我可能会生成更多案例,以确保它可以处理99.9999%:)谢谢,这是我期待的答案,但我认为可能会有一个奇特的解决办法。“听起来你对提案有个好主意”--我在考虑这个,C++17之前的版本<代码>标准::is_aggregate
和构造函数类型推断会改变一些事情。