Зачем нужны template template параметры?

Приведите, пожалуйста, реальные примеры использования этих параметров, когда без них не обойтись либо они значительно упрощают код.


Ответы (1 шт):

Автор решения: EOF

Давайте посмотрим на код ниже:

#include <vector>
#include <list>

using namespace std;

template <template <typename T> typename Cont>
class Foo
{
private:
    Cont<int> values;
};

template <typename Cont>
class Bar
{
private:
    Cont values;
};

int main()
{
    Foo<vector> fooVec;
    Bar<vector<int>> barVec;
    
    Foo<list> fooList;
    Bar<list<int>> barList;
    
    return 0;
}

Как видно, мы можем передать любой контейнер в оба класса. Так в чём разница? Разница в том, что в класс Bar у нас есть возможность передать контейнер другого типа. Нам никто не запрещает написать

Bar<list<double>> barList;

В свою очередь класс Foo дает возможность пользователю класса выбирать необходимый контейнер для хранения значений, но не дает возможность выбирать тип для этих значений.


Вот ещё один вариант использования. Например Вам необходимо хранить в обьекте класса два контейнера. И Вам важно, чтобы это были одинаковые контейнеры.

#include <iostream>
#include <vector>
#include <list>

template <typename Type1, typename Type2, template<typename T> typename Cont>
class Foo
{
private:
    Cont<Type1> first;
    Cont<Type2> second;
};

int main()
{
    Foo<int, double, std::vector> obj1;
    Foo<char, bool, std::list> obj2;
    
    return 0;
}

Передавая шаблон в качестве параметра, Вы сможете гарантировать, что first и second будут одинаковыми контейнерами.


Эта возможность языка чаще используется в метапрограммировании. Попробуйте поискать на гитхабе такие библиотеки. Но начать можете с Boost. В его составе есть MPL (Metaprogramming Library), в которой есть шаблон класса quote*, который использует template template parameter.
Synopsis:

template<
      template< typename P1 > class F
    , typename Tag = unspecified
    >
struct quote1
{
    // unspecified
    // ...
};

...

template<
      template< typename P1,... typename Pn > class F
    , typename Tag = unspecified
    >
struct quoten
{
    // unspecified
    // ...
};
→ Ссылка