在 C++ 中更改模板模板参数

Altering template template parameters in C++

我想设计一个 class 来创建内部类型,这些内部类型是作为模板参数传递的类型的变体。类似于以下非功能性示例:

template <typename T>
class BaseClass
{
public:
    typedef T InternalType;
    std::vector<InternalType> storage;
};

template <typename Base>
class Injector
{
public:
    typedef std::pair<typename Base::InternalType, typename Base::InternalType> RefinedType;
    Base<RefinedType> refinedStorage;
};

typedef Injector<BaseClass<int> > InjectedInt; // Should store vector<pair<int, int> >

由于 Base 是完全指定的类型,Base<RefinedType> refinedStorage; 将无法编译。简单地使用模板模板参数是行不通的,因为细化类型需要基于嵌套模板的参数及其基本类型。

如何实现这种基于模板参数的完全指定类型和基本类型创建类型的模式?

编辑:我希望这是一个任意深度的组合,具有多种注入器类型,执行级联转换。因此,同时传递模板模板参数和基本参数变得非常笨拙(尤其是在处理复合材料的基本情况时),理想的解决方案是使用更直接的语法。

我能够通过显式 're-declaring' 自身内部的通用模板实现这一点:

template <typename T>
class BaseClass
{
public:
    typedef T InternalType;
    std::vector<InternalType> storage;

    template<class T2>
    using Recur = BaseClass<T2>;
};

template <typename Base>
class Injector
{
public:
    typedef std::pair<typename Base::InternalType, typename Base::InternalType> RefinedType;
    typename Base::template Recur<RefinedType> refinedStorage;
};

typedef Injector<BaseClass<int> > InjectedInt; // Should store vector<pair<int, int> >

您可以提供外部重新装订器:

template <class Bound, class U>
struct rebinder;

template <template <class> class Binder, class B, class U>
struct rebinder<Binder<B>, U>
{
  typedef Binder<U> type;
};

// Usage:

template <typename Base>
class Injector
{
public:
    typedef std::pair<typename Base::InternalType, typename Base::InternalType> RefinedType;
    typename rebinder<Base, RefinedType>::type refinedStorage;
};

[Live example]

您可以引入一个 rebind 模板:

template <typename From, typename To>
struct rebind_1st;

template <template <typename... > class Cls, typename A0, typename... Args, typename To>
struct rebind_1st<Cls<A0, Args...>, To> {
    using type = Cls<To, Args...>;
};

template <typename From, typename To>
using rebind_1st_t = typename rebind_1st<From, To>::type;

你的 Injector 变成:

template <typename Base>
class Injector
{
public:
    typedef std::pair<typename Base::InternalType, 
                      typename Base::InternalType> RefinedType;
    rebind_1st_t<Base, RefinedType> refinedStorage;
};

不需要重新绑定模板,那样会使情况过于复杂。简单地有一个模板模板类型:

template<typename>
struct Injector;

template<typename T, template<typename> class Base>
struct Injector<Base<T>>{
    using refined_type = std::pair<typename Base::InternalType, typename Base::InternalType>;
    Base<refined_type> refined_storage;
};

您必须使用模板特化从模板模板中获取具体类型。

这是这样使用的:

using injector_int = Injector<Base<int>>;

int main(){
    injector_int i;
}

here's a live example