шаблонные рекурсивные типы данных - PullRequest
11 голосов
/ 25 марта 2012

У меня есть рекурсивный тип данных, подобный этому:

template<typename T>
struct SomeType {
    std::map<T, SomeType<T>> mapping;
};

SomeType<int> foo;

Это прекрасно работает, но замена std::map на std::unordered_map приводит к ошибке компиляции из-за неполного типа.Я (или gcc) делаю ошибку где-нибудь?или это просто часть стандарта?

Я также хотел бы, чтобы внутренний контейнер определялся параметром шаблона (например, std::stack и std::queue), но я не могу найти способсделайте это, так как это потребует, чтобы SomeType уже был определен.

Неполный пример:

template<typename T, typename C = std::map<T, SomeType<[???]>>>
struct SomeType {
    C mapping;
};

SomeType<int, [???]> foo;

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

Ответы [ 3 ]

7 голосов
/ 25 марта 2012

Ваш класс неполон где-либо до окончательного } его определения.Таким образом, элемент mapping использует неполный тип SomeType в аргументах шаблона своего типа.

Стандарт этого не допускает, и просто удача, что он работает с некоторыми контейнерами STL.*

Ваши вторые вопросы подпадают под тот же ответ - это незаконно, во-первых.

4 голосов
/ 25 марта 2012

Вы не можете определить шаблон с рекурсивными параметрами по умолчанию по очевидным причинам. Вы также не можете создавать экземпляры шаблонов контейнеров стандартной библиотеки для неполных типов, потому что стандарт говорит об этом (в противном случае это неопределенное поведение). Может помочь обычная идиома PIMPL:

#include <map>
#include <memory>
template <typename T> class SomeType
{
    typedef std::map<T, SomeType<T>> map_type;
    typedef std::unique_ptr<map_type> map_ptr;
    map_ptr pimpl;
public:
    SomeType() : pimpl(new map_type) { }
};
3 голосов
/ 25 марта 2012

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

template<typename T, template <typename U, typename V, typename... Args> class Container = std::unordered_map >
struct SomeType {
    Container<T, std::unique_ptr<SomeType> > mapping;
};
...