检查模板参数是否具有随机访问迭代器

Mel*_*kon 0 c++ templates iterator template-meta-programming

我对元编程完全不熟悉,我有一些问题.我想写它有不同的内部表示,并使用不同的算法,如果传递的容器ContainerRandom Access Iterator.但是,我不知道如何检查它.

更新:现在我正在尝试以下内容:

template <typename Container>
struct HaveRandomAccessIterator
{
    typedef char yes[1];
    typedef char no[2];

    template <typename C>
    static yes& test (typename std::random_access_iterator_tag*);
    template <typename>
    static no& test (...);

    static const bool value = sizeof(test<std::iterator_traits<typename Container::iterator*>::iterator_category*>(0)) == sizeof(yes);
};
Run Code Online (Sandbox Code Playgroud)

但是它给了我std :: list的真正价值,并且我得到编译错误,因为在那种情况下我使用operator []

有人可以解释我怎样才能正确检查?

Man*_*rse 5

您的HaveRandomAccessIterator模板过于复杂,有更简单的方法可以实现相同的结果.

基于迭代器类型更改算法的一种标准方法是tag-dispatch:

//First, a helper type alias
template<typename Container>
using IteratorCategoryOf =
    typename std::iterator_traits<typename Container::iterator>::iterator_category;

template<typename Container>
void algorithm(Container &c, std::forward_iterator_tag) {
    //do generic version of algorithm
}

template<typename Container>
void algorithm(Container &c, std::random_access_iterator_tag) {
    //do random-access version of algorithm
}

template<typename Container>
void algorithm(Container &c) {
    algorithm(
        c,
        IteratorCategoryOf<Container>());
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用SFINAE std::enable_if.我怀疑这是你的目标,但HaveRandomAccessIterator可以用std::is_base_of更简单的方式编写:

template<typename Container>
using HaveRandomAccessIterator =
    std::is_base_of<
        std::random_access_iterator_tag,
        IteratorCategoryOf<Container>>;

template<
    typename Container,
    typename std::enable_if<!HaveRandomAccessIterator<Container>::value>::type * = nullptr>
void algorithm(Container &c) {
    //do generic version of algorithm
}

template<
    typename Container,
    typename std::enable_if<HaveRandomAccessIterator<Container>::value>::type * = nullptr>
void algorithm(Container &c) {
    //do random-access version of algorithm
}
Run Code Online (Sandbox Code Playgroud)

如果需要C++ 03兼容性,则可以使用继承而不是类型别名,并将boost对应于std::enable_ifstd::is_base_of.