специализированный шаблон с внутренним шаблоном класса шаблона класса - PullRequest
0 голосов
/ 24 августа 2018

У меня есть библиотека 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<> содержит параметры шаблона, которые не выводятся. Можно ли специализировать шаблон с типом шаблона, то есть внутренним типом другого шаблона? Если нет, то как может выглядеть возможный обходной путь?

1 Ответ

0 голосов
/ 24 августа 2018

typename someClass<T>::type не вычитается.

Обходной путь - определить класс не как внутренний тип:

namespace detail
{
    template<typename T, typename Base>
    struct radio : buffers<radio<T, Base>>, Base
    {
    };
}

template < typename Base >
struct radio_factory
{
    template <typename T>
    using radio = details::radio<T, Base>; // Same interface as before
};

template <typename T, typename Option>
struct trait<detail::radio<T, radio_with_enryption_base<Option>>>
{
    using mapping = short;
};

Демо

...