是否有更好的方法来区分可调整大小的容器而不是allocator_type的存在?

时间:2015-06-21 19:43:45

标签: c++ templates boost containers enable-if

我有$(document).ready(function() { $('[data-toggle="popover"]').popover({ html: true, animation: false, content: 'World', placement: "bottom" }); }); 的模板重载,我需要区分可以调整大小的容器,例如.well-car { width:250px; height:250px; border:10px solid red; float: left; } 和不能的容器,例如operator>>()。我目前只是使用vector特征的存在(参见下面的代码) - 它工作正常 - 但是想知道是否有更明确的方法来测试它。

array

4 个答案:

答案 0 :(得分:4)

如果你想测试容器是resize能否,你应该检查一下它是否有resize()功能。在C ++ 03中,它看起来像:

template <typename T>
class has_resize
{
private:
    typedef char yes;
    struct no {
        char _[2];
    };

    template <typename U, U>
    class check
    { };

    template <typename C>
    static yes test(check<void (C::*)(size_t), &C::resize>*);

    template <typename C>
    static no test(...);

public:
    static const bool value = (sizeof(test<T>(0)) == sizeof(yes));
};

答案 1 :(得分:1)

是。您需要定义/使用自定义特征(如boost::spirit::traits是)。

分配器的存在或缺失并不能真正告诉您容器是否是固定大小的。非标准容器可能根本没有allocator_type关联类型,同时仍允许resize(...)

事实上,因为你有效断言概念允许

C::resize(size_t)

你可以只使用表达式SFINAE

答案 2 :(得分:1)

现代C ++有一种非常简洁的方式:

resize

Demo

现在,如果您不需要在名称为decltype的成员函数和成员变量之间消除歧义,则可以按如下方式编写上述decltype( (void) &T::resize, 0 )

void

请注意,对partial的强制转换是为了处理类型重载逗号运算符并进行泛化失败的情况(因此它比对不起的策略更安全)

答案 3 :(得分:0)

感谢@ Jarod42对单独问题的帮助,我有一个适用于C ++ 98,C ++ 03和C ++ 11的解决方案; g ++和VS2015。此外,对于问题儿童std::vector<bool>

#define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature)                \
    template <typename U>                                                    \
    class traitsName                                                         \
    {                                                                        \
    private:                                                                 \
        typedef boost::uint8_t yes; typedef boost::uint16_t no;              \
        template<typename T, T> struct helper;                               \
        template<typename T> static yes check(helper<signature, &funcName>*);\
        template<typename T> static no check(...);                           \
    public:                                                                  \
        static const bool value = sizeof check<U>(0) == sizeof(yes);         \
    }

DEFINE_HAS_SIGNATURE(has_resize_1, T::resize, void (T::*)(typename T::size_type));
DEFINE_HAS_SIGNATURE(has_resize_2, T::resize, void (T::*)(typename T::size_type, \
    typename T::value_type));

以下是它的使用方法。请注意,has_resize_1的{​​{1}}和has_resize_2成员函数签名都会被检查。那是因为在C ++ 11之前,resize()有一个带有两个参数的签名,最后一个带有默认值;从C ++ 11开始,它有两个签名 - 一个有一个参数,另一个有两个参数。此外,VS2015显然有三个签名 - 以上所有。解决方案就是一直检查两个签名。

可能有一种方法可以将两个检查组合成一个单一的特征,例如resize()。如果你知道,请告诉我。

has_resize<C>::value