我有一个蓝牙库,该库将link_layer
定义为最低的协议层,它在radio
之上实现了链路层协议。 link_layer
本身是一个模板,允许使用不同的radio
实现。 radio
本身也是模板,以允许使用不同的基本配置(例如缓冲区大小)。
许多无线电实现可以共享一些常见的行为,例如buffers
。因此,某些无线电实现通过继承(CRTP)来结合许多实现。
现在,在buffer
实现中需要一些细节,具体取决于实际的radio
实现(内存中和空中PDU布局之间的mapping
)。在无线电中将mapping
定义为一种类型的明显解决方案是行不通的,因为无线电继承了buffer
实现,并且在buffer
模板实例化时,{{ 1}}因此仍然是不完整的类型。
此问题的推荐解决方案是将映射定义为类型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, "" );
}
的部分专业化包含不可推论的模板参数。是否可以使用模板类型(即另一个模板的内部类型)来专门化模板?如果没有,可能的解决方法是什么样子?
答案 0 :(得分:2)
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;
};