如何解决可选的嵌套类型像std :: allocator_traits? [英] How to resolve optional nested type like std::allocator_traits?
问题描述
分配器可以可选地具有嵌套类型,例如 pointer
, const_pointer
。但是总是可以使用 std :: allocator_traits< Allocator>
这些接口来提供这些类型的默认版本,如果它们不在 Allocator
。
如何实现 std :: allocator_traits
如果模板缺少,模板如何选择默认版本的嵌套类型?
解决方案是引用< c $ c> T :: pointer 在上下文中,如果它不是有效的类型,它不会导致错误,而是导致模板参数的扣除失败。其一般形式被称为SFINAE,其代表替换失败不是错误。有关其工作原理的解释,请参阅我的 SFINAE功能不是奥秘Esoterica 演示文稿。 p>
有各种技术,通常涉及重载的函数模板,但我当前的喜欢使用 void_t
idiom选择部分专业化类模板:
template< typename T>
using void_t = void;
template< typename T,typename = void>
struct get_pointer
{
using type = typename T :: value_type *;
};
template< typename T>
struct get_pointer< T,void_t< typename T :: pointer>>
{
using type = typename T :: pointer;
};
现在给定一个分配器类型 A
使用 typename get_pointer< A> :: type
引用 A :: pointer
$ c> A :: value_type *
上述代码起作用,因为当 A :: pointer
是部分专门化匹配的有效类型,比主模板更专业,因此被使用。当 A :: pointer
不是有效类型时,部分专业化不成型,因此使用主模板。
An allocator can optionally have nested types like pointer
, const_pointer
. But one can always use these interface with std::allocator_traits<Allocator>
, which would provide a default version of these types if they are absent in Allocator
.
How is std::allocator_traits
implemented? How can a template choose a default version of nested type when it's absent?
The solution is to refer to the type T::pointer
in a context where it does not cause an error if it is not a valid type, instead it causes template argument deduction to fail. The general form of this is known as SFINAE, which stands for "Substitution Failure Is Not An Error". For a explanation of how it works see my SFINAE Functionality Is Not Arcane Esoterica presentation.
There are various techniques, often involving overloaded function templates, but my current favourite uses the void_t
idiom to select a partial specialization of a class template:
template<typename T>
using void_t = void;
template<typename T, typename = void>
struct get_pointer
{
using type = typename T::value_type*;
};
template<typename T>
struct get_pointer<T, void_t<typename T::pointer>>
{
using type = typename T::pointer;
};
Now given an allocator type A
you can use typename get_pointer<A>::type
to refer to A::pointer
if that exists, otherwise A::value_type*
The code above works because when A::pointer
is a valid type the partial specialization matches and is more specialized than the primary template, and so gets used. When A::pointer
is not a valid type the partial specialization is ill-formed, so the primary template is used.
这篇关于如何解决可选的嵌套类型像std :: allocator_traits?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!