Если я правильно понял вопрос, вы спрашиваете, как работает общий дизайн.
Проблема, которую необходимо решить, заключается в возможности предоставить значение для одного из аргументов шаблона без необходимости указывать его для всех предыдущих аргументов. И решение состоит в том, чтобы переместить типы из аргументов в шаблон в typedefs в базовом классе, а затем замаскировать некоторые конкретные typedefs с аргументами в измененный шаблон.
Коротко о псевдокоде, где пользователь сказал:
X< default1, default2, override3 > // forced to provide default1 and default2!
Мы хотим, чтобы она сказала:
X< modifyArgument3With< override3 > >
Решение, которое они предлагают, заключается в создании иерархии типов, где база содержит значения по умолчанию:
struct DefaultPolicies {
typedef Default1 P1;
...
typedef DefaultN PN;
};
И затем маскирование базовых типов посредством наследования. Подумайте о простоте определения производного типа вручную MyPolicies
, например:
struct MyPolicies : DefaultPolicies {
typedef OverrideX PX;
typedef OverrideY PY;
};
Если вы сделаете: MyPolicies::PX
или MyPolicies::PY
, вы получите переопределения, но для любого другого типа PN
вы получите тип по умолчанию, определенный в базовом классе.
Теперь вам нужно уметь автоматически создавать эквивалент MyPolicies
. Для этого они создают параллельную иерархию типов с виртуальным наследованием для создания PolicySelector
(что эквивалентно MyPolicies
). Я считаю, что это также можно сделать с помощью линейной иерархии (это тип решения, который Александреску предоставляет в Modern C ++ Design ), но для этого требуется использование списков типов, которые добавляют дополнительный код. В C ++ 11 линейная иерархия становится намного проще с аргументами переменных шаблонов, но в C ++ 98 вам придется написать совсем немного, чтобы поддержать список.