首页 > 解决方案 > 有没有办法存储模板参数包并在以后重用它?

问题描述

我有很长的参数包。我想知道有没有办法存储参数包并在以后重用它。例如,如果有 2 个模板:

template<class ... Types> struct A {};
template<class ... Types> struct B {};

我有一个专门的类型:

typedef A<int, int, float> A1_t;

是否有任何操作可以让我创建一个使用与 A1_t 相同的参数包的专用类型 B?( B<int, int, float>)。有什么方法可以<int, int, float>从 A1_t 检索或存储它吗?

我想获得一个专门的类型 B1_t 而不是创建 B1_t 的对象。

A 和 B 描述了完全不同的概念,所以我不能让 B 嵌套在 A 中。

此外,我还想将参数包提供给专门的功能模板。

template<class ...Ts>
C<Ts...> func1()
{
}

所以我可以直接打电话func1<int, int, float>() 如果我能做这样的事情会很好:

template<typename T>
transform<B, T> func1()
{
}

下一步将与此类似:

template<template<class...Ts> templ>
B<Ts...> func2(Ts ...args)
{
}

所以我可以func2<A1_t>(1, 2, 3.0f)直接做。

标签: c++c++17

解决方案


像这样的东西?使用基于偏特化的类型转换:

#include<type_traits>

template<template<typename...> class, typename>
struct with_tmpl_args_of;

template<template<typename...> class OtherTmpl, template<typename...> class Tmpl, typename... Args>
struct with_tmpl_args_of<OtherTmpl, Tmpl<Args...>> {
    using type = OtherTmpl<Args...>;
};

template<template<typename...> class OtherTmpl, typename T>
using with_tmpl_args_of_t = typename with_tmpl_args_of<OtherTmpl, T>::type;

// example

template<class ... Types> struct A {};
template<class ... Types> struct B {};

using A1_t = A<int, int, float>;

using B1_t = with_tmpl_args_of_t<B, A1_t>;

// test

static_assert(std::is_same_v<B1_t, B<int, int, float>>);

这仅限于不使用非类型模板参数的类模板。遗憾的是,目前没有办法在同一个模板模板参数的参数中定义同时接受类型和非类型模板参数的模板模板参数。

还要注意默认参数。如果' 的默认参数之一与模板列表中的该位置匹配,则这将不使用OtherTmpl' 的默认参数,并且如果' 的模板列表(包括默认参数)大于s,则将失败。TmplTmplOtherTmpl


关于您编辑中的其他示例:

第二个示例直接使用我上面定义的类型转换:

template<typename T>
with_tmpl_args_of_t<B, T> func1()
{
}

第三个可以这样完成:

template<typename A, typename... Ts>
with_tmpl_args_of_t<B, A> func2(Ts... args)
{
}

它保证返回类型具有与 相同的模板参数A1_t,但它确实接受所有类型作为参数,即使它们与 的模板参数中的类型不匹配A1_t。这通常不是问题。如果类型不能转换为正确的类型,您将在尝试转换时遇到错误。

如果您必须采用与 for 函数参数的模板参数中完全相同的类型A1_t,您可以执行类似(未经测试)的操作:

template<typename T>
struct func_with_tmpl_args_of;

template<template<typename...> class Tmpl, typename... Args>
struct func_with_tmpl_args_of<Tmpl<Args...>> {
    template<typename F>
    struct inner {
        constexpr inner(F f) : f(std::move(f)) {}
        constexpr static decltype(auto) operator()(Args... args) const {
            return f(std::forward<Args>(args)...);
        }
    private:
        F f;
    };
};

// example

template<typename T>
constexpr inline auto func2 = func_with_tmpl_args_of<T>::inner{[](auto... args)
  -> with_tmpl_args_of_t<B, T> {
    // actual function body
}};

推荐阅读