Как объявить / определить класс с параметрами шаблона шаблона без использования дополнительного параметра шаблона - PullRequest
3 голосов
/ 24 ноября 2008

Рассмотрим следующее использование параметров шаблона шаблона ...

#include <iostream>

template <typename X>
class A
{
    X _t;
public:
    A(X t)
        :_t(t)
    {
    }
    X GetValue()
    {
        return _t;
    }
};

template <typename T, template <typename T> class C >
class B
{
    C<T> _c;
public:
    B(T t)
        :_c(t)
    {
    }
    T GetValue()
    {
        return _c.GetValue();
    }
};

using namespace std;

int main()
{
    B<int, A> b(10);
    cout<<b.GetValue();
    return 0;
}

Есть ли способ, которым параметр шаблона T может быть удален? Например, есть ли способ заставить следующую работу?

//Does not compile
template <template <typename T> class C >
class B
{
    C _c;
public:
    B(T t)
        :_c(t)
    {
    }
    T GetValue()
    {
        return _c.GetValue();
    }
};

int main()
{
    B< A<int> > b(10);
    cout<<b.GetValue();
    return 0;
}

Ответы [ 4 ]

8 голосов
/ 24 ноября 2008

Я полагаю, что вы после X, а также A, в вашем коде.

Обычный шаблон должен иметь

template<typename C>
struct B
{
   C c;
};

и затем внутри классов, имеющих право на замену:

template<typename X>
class A
{
   typedef X type_name;
   X t;
};

Затем вы можете получить доступ к параметру шаблона, используя C::type_name.

4 голосов
/ 24 ноября 2008

Это невозможно. Обратите внимание, что это распространенное заблуждение: A<int> больше не шаблон класса! Поэтому он не подходит для параметра шаблона-шаблона, но должен быть принят с использованием параметра типа:

template<typename C>
struct B {
    C c;
};

B< A<int> > b;

Ваш способ использования отдельного параметра в порядке.

Если вы хотите принять A<int>, но хотите повторно привязать его к другому параметру, вы можете использовать этот шаблон, также используемый стандартными распределителями:

template<typename T>
struct A {
    template<typename U>
    struct rebind {
        typedef A<U> type;
    };
};

template<typename C>
struct B {
    typename C::template rebind<float>::type c;
};

B< A<int> > b;

Теперь B< A<int> >::c относится к типу A<float>. typename перед C:: сообщает компилятору, что ::type в конце является типом, а не статическим нетипичным членом. template после C:: сообщает компилятору, что rebind<float> является экземпляром шаблона, а не сравнением.

1 голос
/ 24 ноября 2008

Вы можете вкладывать параметры. То есть значение параметра само может быть параметризовано.

template <typename X>
struct A
{
  X t;
};

template <typename  C>
struct B
{
  C c;
};

int main()
{
  B< A<int> > b;
  return 0;
}

В этом примере объявление b в main() создает специализацию A, используя int в качестве параметра, затем создает специализацию B, используя A<int> в качестве параметра. Таким образом, в специализации B, C есть A<int>.

1 голос
/ 24 ноября 2008

Что не так с:

template <typename C >
struct B
{
    C c;
};

int main()
{
    B< A<int> > b;
    return 0;
}
...