10

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

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

4 回答 4

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> >
于 2015-07-13T13:16:27.990 回答
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;
};
于 2015-07-13T13:19:42.913 回答
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;
}

这是一个活生生的例子

于 2015-07-13T13:24:19.147 回答
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;
};

[现场示例]

于 2015-07-13T13:18:15.880 回答