2014-05-24 26 views
0

我对元编程完全陌生,并且有一些问题。 我想写一个容器,它具有不同的内部表示形式,如果传递的ContainerRandom Access Iterator,则使用不同的算法。但是,我不知道如何检查它。检查模板参数是否具有随机访问迭代器

UPDATE:现在我正在尝试与以下:

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

然而,它给我的std ::名单的真正价值,而我得到的编译错误,因为在这种情况下,我使用operator []

有人可以解释我怎么才能正确地检查它?

回答

5

HaveRandomAccessIterator模板过于复杂,有实现相同的结果的简单的方法。改变迭代器型的基础上的算法

一种标准方式是标签的调度:

//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>()); 
} 

或者,您也可以通过std::enable_if使用SFINAE。我怀疑这是你的目标是什么,但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 
} 

如果需要C++ 03的兼容性,您可以使用继承,而不是类型 - 别名,以及std::enable_ifstd::is_base_of的增强对应。

+0

非常感谢! :) – Melkon

1

它应该是:

static yes& test (typename std::iterator_traits<typename C::iterator*>::random_access_iterator_tag*); 

SFINAE以这种方式工作。

而且,我发现下面的更优雅:

struct yes{}; 
struct no {}; 

enum { value = std::is_same<yes, [test-here]>::value }; 
+0

Whao,那么愚蠢的错从我,非常感谢你! 但是,它始终有错误的值,即使对于std :: vector也是如此。 – Melkon

+2

'iterator_traits'具有'iterator_category'成员typedef。 'random_access_iterator_trag'是'std'命名空间中的一个标签。 – erenon

+0

嗯,我真的不明白我应该如何解决这个问题。现在我正在尝试这个:'静态是&测试(typename std :: random_access_iterator_tag *); (0))== sizeof(yes);}} sizeof(yes);} ' 但是,它给列表真正的价值,并给我编译错误,当我想使用operator [] – Melkon

相关问题