Ответ в том, что вы не можете заниматься этой специализацией. Это не синтаксическая ошибка, а просто то, что не может быть реализовано. Вы должны увидеть специализации шаблонов, немного похожие на перегрузку функций. Компилятор должен взять аргумент типа на сайте использования, посмотреть доступные специализации, найти совпадения и выбрать лучший (самый специализированный). Проблема с вашим примером состоит в том, что шаг "найти совпадение" не может быть реализован с такой специализацией. Компилятор может ожидать, что «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 ++ на этом заканчиваются. Очень часто, чтобы узнать, следует ли ожидать, что компилятор сможет что-то решить, просто поставьте себя на место и посмотрите, возможно ли это хотя бы отдаленно (ответ обычно ясен).