Вопрос

Is there a way to extract a partial default specialization from the compiler?

Say that I have this two parameter template:

template<typename A, typename B>
struct X {
    A a;
    B b;
};

and I also have some code that makes use of a single parameter template, like this:

template<template<typename> class T, typename B>
struct make_T_of_B {
    T<B> member;
};

I'd like to be able to say:

make_T_of_B<X<int>, double> dummy;

where X<int> is taken as a single parameter template. It would be equivalent to this template:

template<typename B>
struct Y {
    int a;
    B b;
};

which looks like how one would specialize X<int, B> without actually changing anything. It's in a way similar to a default specialization -- except that a default specialization doesn't produce another template but rather an actual type (in other words, it's always total).

I realize that I can cascade the template arguments

template<typename A>
struct Z1 {
    // start from scratch
    template<typename B>
    struct Z2 {
        A a;
        B b;
    };

    // inherit from double template above
    template<typename B>
    struct X: ::X<A, B> {}; 
};


make_T_of_B<Z1<int>::Z2, double> dummy1;
make_T_of_B<Z1<int>::X, double> dummy2;

but I find that to be rather hard to read and not communicate my intentions clearly.

Thank you.

Это было полезно?

Решение

I misunderstood your question. All you want is a way to bind the first template parameter, which you can do easily like this:

template <typename T> using Foo = X<int, T>;

Now Foo<double> is the same as X<int, double>.

Without C++11-style aliases, you can achieve the same with a bit more boilerplate:

template <typename T> struct Foo
{
    typedef X<int, T> type;
};

Now you use Foo<double>::type.

Другие советы

I'd use a trait:

template <typename> struct applicator;

template <template <typename> class Tmpl, typename T>
struct applicator<Tmpl<T>>
{
    template <typename A>
    using rebind = make_T_of_B<Tmpl, A>;
};

Now you can say:

applicator<X<int>>::rebind<double> dummy;

You can of course also move the second argument, A, into the main template:

template <typename, typename> bpplicator;

template <template <typename> class Tmpl, typename T, typename A>
struct bpplicator<Tmpl<T>, A>
{
    using type = make_T_of_B<Tmpl, A>;  // or "typedef make_T_of_B<Tmpl, A> type;"
};

bpplicator<X<int>, double>::type dummy;

This has the advantage that it works in C++03, too.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top