У меня есть библиотека Bluetooth, которая определяет link_layer
как самый низкий уровень протокола, который реализует протокол канального уровня поверх radio
. Сам link_layer
является шаблоном, позволяющим использовать различные реализации radio
. radio
сам по себе также является шаблоном, позволяющим использовать различные базовые конфигурации (например, размеры буфера).
Многие радиопрограммы могут иметь общее поведение, например buffers
. Таким образом, некоторые из реализаций радио объединяют много реализаций, наследуя их (CRTP).
Теперь мне нужны некоторые подробности в реализации buffer
, которые зависят от фактической реализации radio
(mapping
между памятью и сетевым распределением PDU). Очевидное решение - определить, что mapping
как тип в радио, не работает, потому что радио наследует реализацию buffer
, и в момент создания шаблона buffer
шаблон radio
, таким образом, все еще не завершен. тип.
Рекомендуемое решение этой проблемы - определить это отображение как тип trait
и специализировать trait
для всех реализаций radio
. Это сработало очень хорошо, потому что есть разумное значение по умолчанию, которое работает для многих radio
с.
Помимо buffer
, есть другая деталь реализации (шифрование), которую я смешиваю с реализацией radio
через наследование. В одном из случаев, когда мне нужно специализировать trait
сверху, этот тип снова является шаблоном. Я смешиваю разные типы поддержки шифрования, используя factory
, который определяет шаблон radio
как результат. Вот краткий набросок сценария:
#include <type_traits>
template < typename OtherOption, template < typename > class Radio >
struct link_layer : Radio< OtherOption >
{
};
template < class ConfiguredRadio >
struct trait
{
using mapping = int;
};
template < typename ConfiguredRadio >
struct buffers
{
using mapping = typename trait< ConfiguredRadio >::mapping;
};
template < typename Base >
struct radio_factory
{
template < typename T >
struct radio : buffers< radio< T > >, Base
{
};
};
struct radio_without_enryption_base {};
template < typename Option >
struct radio_with_enryption_base {};
template < typename Option, typename T >
struct trait<
typename radio_factory<
radio_with_enryption_base< Option >
>::template radio< T >
>
{
using mapping = short;
};
template < typename OtherOption >
using ll_without_encryption = link_layer<
OtherOption,
radio_factory< radio_without_enryption_base >::template radio >;
template < typename OtherOption >
using ll_with_encryption = link_layer<
OtherOption,
radio_factory< radio_with_enryption_base< OtherOption > >::template radio >;
int main()
{
static_assert( std::is_same< ll_without_encryption< int >::mapping, int >::value, "" );
static_assert( std::is_same< ll_with_encryption< int >::mapping, short >::value, "" );
}
Все компиляторы, которые я пробовал, жалуются, что частичная специализация trait<>
содержит параметры шаблона, которые не выводятся. Можно ли специализировать шаблон с типом шаблона, то есть внутренним типом другого шаблона? Если нет, то как может выглядеть возможный обходной путь?