在SFINAE上下文中编写allocator_traits<T>::value_type似乎是测试T类型是否实际上是分配器的可行方法。然而,这并不是特别优雅,我过去也曾被角落的案例所灼伤。所以我的问题是:如何最好地实现一个is_allocator<T> traits,在T是分配器的情况下,它包含一个为true的::value,而在其他情况下,它包含::false?
allocator_traits<T>::value_type
T
is_allocator<T>
::value
gstyhher1#
在SFINAE上下文中编写allocator_traits<T>::value_type似乎是测试T类型是否实际上是分配器的可行方法。我认为这还不够。这只会检查T是否有一个value_type并且是可重新绑定的。libstdc和libc都将std::map<int, int>视为该模型中的分配器。该标准有一个构成Allocator的要求表。我认为你最好的办法是检查几个表达式的有效性,即:
value_type
std::map<int, int>
Allocator
X::value_type
a.allocate(n)
X::pointer
a.deallocate(p, n)
(其中X是要检查的类型,a是X&,n是allocator_traits<X>::size_type类型的值)如果有一种类型,检查了所有这些盒子,仍然不是一个allcoator,那么... ¯_()_/¯.
X
a
X&
n
allocator_traits<X>::size_type
ryevplcw2#
为了完整起见,下面是@巴里的答案的C++20概念:
template <typename Allocator> concept is_allocator = requires(Allocator a, typename Allocator::value_type* p) { { a.allocate(0) } -> std::same_as<decltype(p)>; { a.deallocate(p, 0) } -> std::same_as<void>; };
活生生的例子
2条答案
按热度按时间gstyhher1#
在SFINAE上下文中编写
allocator_traits<T>::value_type
似乎是测试T
类型是否实际上是分配器的可行方法。我认为这还不够。这只会检查
T
是否有一个value_type
并且是可重新绑定的。libstdc和libc都将std::map<int, int>
视为该模型中的分配器。该标准有一个构成
Allocator
的要求表。我认为你最好的办法是检查几个表达式的有效性,即:X::value_type
a.allocate(n)
有效并返回X::pointer
a.deallocate(p, n)
有效(其中
X
是要检查的类型,a
是X&
,n
是allocator_traits<X>::size_type
类型的值)如果有一种类型,检查了所有这些盒子,仍然不是一个allcoator,那么... ¯_()_/¯.
ryevplcw2#
为了完整起见,下面是@巴里的答案的C++20概念:
活生生的例子