通用模板模板参数

时间:2017-10-18 14:43:54

标签: c++ templates c++17 template-templates

接受&#34;统一初始化&#34;不是非常统一,我决定编写一个通用的 <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency> 包装器,如果类型是聚合,则使用聚合初始化,否则直接初始化:

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() 具有非类型模板参数,因此它与(1)处的std::array模板模板参数不匹配。

所以我的问题是,有没有办法在(1)处制定参数,使得它可以接受任何类模板名称,无论其类型(类型或非类型)如何模板参数?

1 个答案:

答案 0 :(得分:5)

不幸的是,没有代码重复就没有正确的方法。新添加的&#34; auto作为模板参数&#34;在C ++ 17中只支持非类型模板参数

我认为这可行的唯一方法是使用代码生成器生成autoclass的固定数量的排列。 E.g。

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...

live example on wandbox

听起来你对提案有好主意......