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

pro*_*ble 10 c++ templates template-templates

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

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> >
Run Code Online (Sandbox Code Playgroud)

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

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

编辑:我希望这是一个任意深度的复合,有多个注入器类型执行级联转换.因此,传递模板模板参数和基本参数变得相当笨拙(特别是在处理复合的基本情况时),理想的解决方案将使用更直接的语法.

Pet*_*etr 10

通过明确地"重新声明"内部的通用模板,我能够实现这一目标:

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> >
Run Code Online (Sandbox Code Playgroud)

  • FWIW,这是[`std :: allocator`](http://en.cppreference.com/w/cpp/memory/allocator)如何做到的(除了它们命名为`rebind`,其内部typedef称为` other`). (4认同)

Bar*_*rry 8

你可以介绍一个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;
Run Code Online (Sandbox Code Playgroud)

Injector变成了:

template <typename Base>
class Injector
{
public:
    typedef std::pair<typename Base::InternalType, 
                      typename Base::InternalType> RefinedType;
    rebind_1st_t<Base, RefinedType> refinedStorage;
};
Run Code Online (Sandbox Code Playgroud)


Cof*_*ode 5

不需要重新绑定模板,这会使情况过于复杂.只需要一个模板模板类型:

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;
};
Run Code Online (Sandbox Code Playgroud)

您必须使用模板专门化从模板模板中获取具体类型.

这样使用:

using injector_int = Injector<Base<int>>;

int main(){
    injector_int i;
}
Run Code Online (Sandbox Code Playgroud)

这是一个实例