Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何替换给定类型中的模板参数?_C++_Templates_C++14_Template Meta Programming - Fatal编程技术网

C++ 如何替换给定类型中的模板参数?

C++ 如何替换给定类型中的模板参数?,c++,templates,c++14,template-meta-programming,C++,Templates,C++14,Template Meta Programming,假设名为B的模板参数的类型为C(在实例化时),如何从B构造C 以下是我的代码的一个精简摘录: template<typename A> class foo { template<typename B> // B is guaranteed to always be of the form C<D> // How to write a function here with return type C<A>? } 模板 福班{ 模板/

假设名为
B
的模板参数的类型为
C
(在实例化时),如何从
B
构造
C

以下是我的代码的一个精简摘录:

template<typename A>
class foo {
    template<typename B> // B is guaranteed to always be of the form C<D>
    // How to write a function here with return type C<A>?
}
模板
福班{
模板//B保证始终采用C的形式
//如何在这里编写返回类型为C的函数?
}
您可以使用

模板
结构元{};
模板
结构元{
使用类型=C;
};
meta::type
将是
C

如果您想在基本情况下处理默认参数

template<typename...>
struct meta {};

template<typename A, template<typename...> typename C, typename B, typename ... Ts>
struct meta<A, C<B, Ts...>> {
    using type = C<A, Ts...>;
};
模板
结构元{};
模板
结构元{
使用类型=C;
};

首先,我们编写一些机制来替换模板类型实例中的类型:

template<class In, class Replace>
struct replace_first_type;
template<template<class...>class Z, class T0, class...Ts, class Replace>
struct replace_first_type<Z<T0, Ts...>, Replace> {
  using type=Z<Replace, Ts...>;
};

template<class In, class Replace>
using replace_first = typename replace_first_type<In,Replace>::type;
现在
foo::template result
是一个
std::vector
。无可否认,这是一种相当愚蠢的类型

如果您有一个功能:

  template<class B>
  result<B> do_something() {
    return {};
  }
模板
结果做某事{
返回{};
}
实际上返回该类型的值

我们可以通过递归地替换我们所替换的类型来解决上述
std::allocator
的问题

template<class X, class Src, class Dest>
struct subst_type {
  using type=X;
};
template<class X, class Src, class Dest>
using subst_t = typename subst_type<X, Src, Dest>::type;
template<template<class...>class Z, class...Ts, class Src, class Dest>
struct subst_type<Z<Ts...>, Src, Dest> {
  using type=Z<subst_t<Ts, Src, Dest>...>;
};
template<class Src, class Dest>
struct subst_type<Src, Src, Dest> {
  using type=Dest;
};
模板
结构子类型{
使用类型=X;
};
模板
使用subst\u t=typename subst\u type::type;
模板
结构子类型{
使用类型=Z;
};
模板
结构子类型{
使用类型=Dest;
};
并首先申请替换:

template<class In, class Replace>
struct replace_first_type;
template<template<class...>class Z, class T0, class...Ts, class Replace>
struct replace_first_type<Z<T0, Ts...>, Replace> {
  using type=Z<Replace, subst_t<Ts, T0, Replace>...>;
};
模板
结构替换第一个类型;
模板
结构替换第一个类型{
使用类型=Z;
};
现在当我们
foo::result
时,我们得到的是
std::vector
,而不是
std::vector
(这是一种无用的类型)


在模板的其余参数中,递归地将
A
替换为
B
,可能会出现严重错误,但是,如果我们不做,我们肯定会得到一些普通模板的可怕的东西。

你对“泰克的方法”有什么想法?@ MySuffic,如果你不需要支持<代码> STD::vector < /Cord>他作品很棒。@ YAKK AdNeNavaRunt它支持C++的默认模板参数。17@Tyker啊,我错过了C++17的功能。而且它可能会重新绑定分配器,而不需要我需要的“替换所有东西”这样的有点危险的命令。@Yakk AdamNevraumont是的,分配器也需要重新绑定。所以不,我的方法在c++17中无法在vector上工作;我读了这两个答案,对我来说这是最有效的方法(避免STL分配器混乱):
template struct meta{};template struct meta{using type=C;/*但我们将模板参数放在第一个参数之后(因此采用默认参数!)*/}也就是说,删除倒数第二行中的省略号(即使用默认参数)。
template<class X, class Src, class Dest>
struct subst_type {
  using type=X;
};
template<class X, class Src, class Dest>
using subst_t = typename subst_type<X, Src, Dest>::type;
template<template<class...>class Z, class...Ts, class Src, class Dest>
struct subst_type<Z<Ts...>, Src, Dest> {
  using type=Z<subst_t<Ts, Src, Dest>...>;
};
template<class Src, class Dest>
struct subst_type<Src, Src, Dest> {
  using type=Dest;
};
template<class In, class Replace>
struct replace_first_type;
template<template<class...>class Z, class T0, class...Ts, class Replace>
struct replace_first_type<Z<T0, Ts...>, Replace> {
  using type=Z<Replace, subst_t<Ts, T0, Replace>...>;
};