Частичная специализация с типом, вложенным в шаблонный класс - PullRequest
6 голосов
/ 24 мая 2011

Я играю с шаблонами и частичной специализацией, но есть одна специализация, которую я не знаю, как писать ... Я упросту код, чтобы его было легче читать.

Давайте разберемся

template <typename T>
    class x
{
    ...
};

Как правило, я могу специализироваться так:

class x<a_type>
{
    ...
};

Также работает с типами шаблонов:

template <typename T>
    class x<std::vector<T>>
{
    ...
}

Теперь я хотел бы сделать специализациютип, вложенный в шаблонный класс:

template <typename T>
    class y
{
    struct nested_type
    {
        y a_member;
    };

    ...
};

// Here comes the specialization

template <typename T>
    class x<y<T>::nested_type>
{
    ...
};

Не удалось.Я также попытался поставить 'typename' перед y :: nested_type, но это не решило проблему.Ошибка компилятора:

type/value mismatch at argument 1 in template parameter list for ‘template <class T> struct x’

То, что я хочу сделать, кажется логичным, но я не уверен, возможно ли это.Я использую C ++ 0x с g ++ - 4.5.Кто-нибудь знает правильный синтаксис для написания такой специализации?

1 Ответ

5 голосов
/ 24 мая 2011

Ответ в том, что вы не можете заниматься этой специализацией. Это не синтаксическая ошибка, а просто то, что не может быть реализовано. Вы должны увидеть специализации шаблонов, немного похожие на перегрузку функций. Компилятор должен взять аргумент типа на сайте использования, посмотреть доступные специализации, найти совпадения и выбрать лучший (самый специализированный). Проблема с вашим примером состоит в том, что шаг "найти совпадение" не может быть реализован с такой специализацией. Компилятор может ожидать, что «nested_type» будет чем угодно, не обязательно уникальным типом (как в вашем примере), это может быть, например, также вложенный typedef. Более того, компилятор не может предсказать, что он уже видит все специализации шаблона "y", поэтому даже если nested_type - это уникальный тип, вложенный в y (общий шаблон), он может быть вложенным typedef в следующем объявлении специализации шаблона для шаблона. "у".

Как и в случае с перегрузкой функций и используемым там алгоритмом сопоставления, компилятор ограничен в своих возможностях для определения типа и того, какие ограничения он допускает. Если у вас есть специализация для x<int> и последующего использования x<int>, совпадение тривиально, вычитания не требуются, предположения не требуются. Если у вас есть специализация, такая как x<T*>, а затем используйте x<int*>, совпадение легко, T может быть выведено как int. Если у вас есть специализация типа x< y<T>::type >, а затем используется любая версия x, как компилятор должен выводить T из y :: type? Необходимо заменить T в y всеми возможными типами, существующими во всем мире, чтобы увидеть, есть ли такой, который приводит к совпадению вложенного типа. Это необоснованное ожидание, и именно поэтому возможности вывода типов в шаблонах C ++ на этом заканчиваются. Очень часто, чтобы узнать, следует ли ожидать, что компилятор сможет что-то решить, просто поставьте себя на место и посмотрите, возможно ли это хотя бы отдаленно (ответ обычно ясен).

...