【发布时间】:2018-08-24 18:10:51
【问题描述】:
我有一个蓝牙库,它将link_layer 定义为最低协议层,它在radio 之上实现了链路层协议。 link_layer 本身是一个模板,允许使用不同的 radio 实现。 radio 本身也是一个模板,以允许不同的基本配置(例如缓冲区大小)。
许多无线电实现可以共享一些共同的行为,例如buffers。所以一些无线电实现通过继承它们(CRTP)结合了很多实现。
现在我需要buffer 实现中的一些细节,这些细节取决于实际的radio 实现(mapping 在内存中和无线 PDU 布局之间)。显而易见的解决方案,将 mapping 定义为收音机中的类型不起作用,因为收音机继承了 buffer 实现,并且在 buffer 模板实例化时,radio 因此仍然是不完整的输入。
此问题的推荐解决方案是将映射定义为 trait 类型,并将 trait 专门用于所有 radio 实现。这很有效,因为有一个合理的默认值,适用于很多 radios。
除了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<> 的部分特化包含不可推导的模板参数。是否可以使用模板类型专门化模板,即另一个模板的内部类型?如果没有,可能的解决方法是什么?
【问题讨论】: