使用类模板的内部类模板专门化模板

时间:2018-08-24 18:10:52

标签: c++ traits crtp

我有一个蓝牙库,该库将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, "" ); } 的部分专业化包含不可推论的模板参数。是否可以使用模板类型(即另一个模板的内部类型)来专门化模板?如果没有,可能的解决方法是什么样子?

1 个答案:

答案 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;
};

Demo