【问题标题】:Correct signature of / detect presence of Container::reserve()正确签名/检测 Container::reserve() 的存在
【发布时间】:2013-02-14 19:31:00
【问题描述】:

给定类型C,它是一个符合STL 的容器,我如何正确检测C 是否包含成员函数reserve?我尝试了以下方法(使用 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
{};

这适用于Cstd::vector,但不适用于无序容器,例如std::unordered_set。原因是,reservestd::vector 的(直接)成员函数,但对于无序容器,它是从基类继承的,即它的签名不是void (C::*)( typename C::size_type ),而是void (B::*)( typename C::size_type ) 对于某些未指定的基类B 的类 C

我知道如何解决它并检测reserve,即使是继承的,但它看起来很笨拙,我想知道标准允许什么。所以...

我的问题是:标准是否允许 reserve 从未指定的基类继承,还是概要绑定并需要直接成员函数?

【问题讨论】:

    标签: c++ c++11 std enable-if


    【解决方案1】:

    所有关于从基类继承的标准都是允许的:

    17.6.5.11 派生类[派生]

    1 - 实现可以从具有为实现保留名称的类派生 C++ 标准库中的任何类。

    它并没有说明方法(实际上还有其他成员,例如 typedefs)是否允许从基类继承。显然,由于实现是这样做的,标准应该描述这种行为。

    在任何情况下,检测例如reserve 通过强制转换为成员函数类型不能保证即使是最派生类型的成员也能正常工作,因为:

    17.6.5.5 成员函数[member.functions]

    2 - 一个实现可以在一个类中声明额外的非虚拟成员函数签名:

    • 通过将具有默认值的参数添加到成员函数签名186; [...]

    186) 因此,C++ 标准库中类的成员函数的地址具有未指定的类型。

    检查reserve是否存在的正确方法是尝试调用它:

    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
    {};
    

    这具有并行容器要求unordered_set 的表 103)的优点,这是规范的,其中提要更倾向于提供信息。

    【讨论】:

    • 在 VS2012 下不编译。有替代方案吗?
    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-04
    相关资源
    最近更新 更多