简体   繁体   中英

specialize template with inner class template of a class template

I have a Bluetooth library that defines a link_layer as the lowest protocol layer, that implements the link layer protocol on top of a radio . The link_layer itself is a template to allow the use of different radio implementations. A radio itself is a template too, to allow for different, basic configurations (eg buffer sizes).

A lot of radio implementation can share some common behavior, like buffers . So some of the radio implementations combine a lot of implementation by inheriting from them (CRTP).

Now I need some details in the buffer implementation that depend on the actual radio implementation ( mapping between in memory and over the air PDU layout). The obvious solution, to define that mapping as a type in the radio does not work, because the radio inherits the buffer implementation and at the point of the buffer template instantiation, the radio is thus still an incomplete type.

Recommended solution to this problem is to define that mapping as a type trait and specialize the trait for all radio implementations. This worked very well, because there is a reasonable default, that works for a lot of radio s.

Beside the buffer , there is a different implementation detail (encryption) that I mix into the radio implementation via inheritance. In one of the cases, where I need to specialize the trait from above, that type itself is again a template. I mix in different encryption supporting types useing a factory , that defines the radio template as result. Here is a short sketch of the scenario:

#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, "" );
}

All compilers I've tried complain, that the partial specialization of trait<> contains template parameters that are not deducible. Is it possible to specialize a template with a template type, that is the inner type of another template? If not, what could a possible workaround look like?

typename someClass<T>::type is not deducible.

workaround is to define the class not as inner 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;
};

Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM