正确签名/检测Container :: reserve()的存在 [英] Correct signature of / detect presence of Container::reserve()
问题描述
给定一个类型 C
这是一个符合STL的容器,如何正确检测 C
是否包含成员函数 reserve
?我试过下面的方法(用GCC 4.6.3):
Given a type C
which is an STL-conforming container, how do I correctly detect if C
contains a member function reserve
? I tried the following approach (with GCC 4.6.3):
template< typename C, typename = void >
struct has_reserve
: std::false_type
{};
template< typename C >
struct has_reserve< C, typename std::enable_if<
std::is_same<
decltype( &C::reserve ),
void (C::*)( typename C::size_type )
>::value
>::type >
: std::true_type
{};
这适用于 C
为 std :: vector
,但不能用于无序容器,例如 std :: unordered_set
。原因是 reserve
是 std :: vector
的(直接)成员函数,但对于无序容器它继承自一个基类,即它的签名不是 void(C :: *)(typename C :: size_type)
,但 void对于
C $ c>的某些未指定的基类
B
$ c>。
This works for C
being std::vector
, but not for the unordered containers, e.g. std::unordered_set
. The reason is, that reserve
is a (direct) member function of std::vector
, but for the unordered containers it is inherited from a base class, i.e., its signature is not void (C::*)( typename C::size_type )
but void (B::*)( typename C::size_type )
for some unspecified base class B
of C
.
我知道如何解决它并检测 reserve
,即使继承,但它看起来笨拙我不知道标准允许什么。所以...
I know how to work around it and detect reserve
even if inherited, but it looks clumsy and I wonder what is allowed by the standard. So...
我的问题是:标准允许 reserve
从一个未指定的基类继承,是概要绑定,需要一个直接成员函数?
My question is: Does the standard allow reserve
to be inherited from an unspecified base class or is the synopsis binding and requires a direct member function?
推荐答案
所有的标准都说关于从基类继承是允许:
All the standard says about inheritance from base classes is that it is allowed:
17.6.5.11派生类[衍生]
可以从保留给实现的名称的类中派生C ++标准库中的任何类。
17.6.5.11 Derived classes [derivation]
1 - An implementation may derive any class in the C++ standard library from a class with a name reserved to the implementation.
是否允许方法(以及实际上其他成员,如typedef)从基类继承;显然,由于实现这样做,标准应该描述这种行为。
It doesn't say either way whether methods (and, indeed, other members such as typedefs) are allowed to be inherited from a base class; obviously, since implementations do so, the standard should describe this behaviour.
在任何情况下, reserve
通过强制转换为成员函数类型,即使是最派生类型的成员也不能保证工作,因为:
In any case, detecting e.g. reserve
by cast to a member function type is not guaranteed to work even if a member of the most derived type, since:
17.6.5.5成员函数[member.functions]
2 - 一个实现可以声明一个class:
17.6.5.5 Member functions [member.functions]
2 - An implementation may declare additional non-virtual member function signatures within a class:
- 通过向成员函数签名 186添加具有默认值的参数; [...]
186)因此,C ++标准库中的类的成员函数的地址具有未指定的类型。
186) Hence, the address of a member function of a class in the C++ standard library has an unspecified type.
检查 reserve
是否存在的正确方法是尝试调用it:
The correct way to check whether reserve
exists is to attempt to call it:
template< typename C, typename = void >
struct has_reserve
: std::false_type
{};
template< typename C >
struct has_reserve< C, typename std::enable_if<
std::is_same<
decltype( std::declval<C>().reserve( std::declval<typename C::size_type>() ) ),
void
>::value
>::type >
: std::true_type
{};
这具有并行容器需求的优点code> unordered_set ),这是规范的,其中的概要更倾向于信息。
This has the advantage of paralleling the container requirements (table 103 for unordered_set
), which are normative where the synopses tend more to the informative.
这篇关于正确签名/检测Container :: reserve()的存在的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!