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

时间:2015-07-13 13:03:58

标签: 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> >

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

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

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

4 个答案:

答案 0 :(得分: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> >

答案 1 :(得分: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;

您的Injector成为:

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

答案 2 :(得分: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;
};

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

这样使用:

using injector_int = Injector<Base<int>>;

int main(){
    injector_int i;
}

here's a live example

答案 3 :(得分:4)

您可以提供外部反叛者:

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]