使用 class 模板的内部 class 模板专门化模板
specialize template with inner class template of a class template
我有一个蓝牙库将 link_layer
定义为最低协议层,它在 radio
之上实现了 link 层协议。 link_layer
本身是一个允许使用不同 radio
实现的模板。 radio
本身也是一个模板,以允许不同的基本配置(例如缓冲区大小)。
很多无线电实现可以共享一些共同的行为,比如 buffers
。所以一些无线电实现通过继承它们(CRTP)来组合很多实现。
现在我需要 buffer
实现中的一些细节,这些细节取决于实际的 radio
实现(mapping
在内存和空中 PDU 布局之间)。显而易见的解决方案是,将 mapping
定义为无线电中的一种类型是行不通的,因为无线电继承了 buffer
实现,并且在 buffer
模板实例化时, radio
因此仍然是一个不完整的类型。
针对此问题的推荐解决方案是将该映射定义为类型 trait
并针对所有 radio
实现专门化 trait
。这非常有效,因为有一个合理的默认值,适用于很多 radio
s。
除了 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<>
的偏特化包含不可推导的模板参数。是否可以使用模板类型专门化模板,即另一个模板的内部类型?如果没有,可能的解决方法是什么?
typename someClass<T>::type
不可推导
解决方法是将 class 定义为非内部类型:
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;
};
我有一个蓝牙库将 link_layer
定义为最低协议层,它在 radio
之上实现了 link 层协议。 link_layer
本身是一个允许使用不同 radio
实现的模板。 radio
本身也是一个模板,以允许不同的基本配置(例如缓冲区大小)。
很多无线电实现可以共享一些共同的行为,比如 buffers
。所以一些无线电实现通过继承它们(CRTP)来组合很多实现。
现在我需要 buffer
实现中的一些细节,这些细节取决于实际的 radio
实现(mapping
在内存和空中 PDU 布局之间)。显而易见的解决方案是,将 mapping
定义为无线电中的一种类型是行不通的,因为无线电继承了 buffer
实现,并且在 buffer
模板实例化时, radio
因此仍然是一个不完整的类型。
针对此问题的推荐解决方案是将该映射定义为类型 trait
并针对所有 radio
实现专门化 trait
。这非常有效,因为有一个合理的默认值,适用于很多 radio
s。
除了 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<>
的偏特化包含不可推导的模板参数。是否可以使用模板类型专门化模板,即另一个模板的内部类型?如果没有,可能的解决方法是什么?
typename someClass<T>::type
不可推导
解决方法是将 class 定义为非内部类型:
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;
};