tags:

views:

56

answers:

2

Given the code below is there a nicer way to right it that doesn't repeat typename std::iterator_traits<T>::iterator_category twice?

template<class T, class T2>
struct foo :
    bar<
        foo<T, T2>, typename 
        std::conditional<
            std::is_same<typename 
                std::iterator_traits<T>::iterator_category,  //Repeated
                std::random_access_iterator_tag
            >::value,
            std::bidirectional_iterator_tag, typename 
            std::iterator_traits<T>::iterator_category       //Repeated
        >::type
    >
{}
A: 

You could typedef it:

typedef std::iterator_traits<T>::iterator_category it_cat;
Flinsch
Is this compileable? Where do you propose to put this code? Note that `T` is a template parameter.
Vlad
@Vlad, can we say:typedef std::iterator_traits<typename T>::iterator_category it_cat;
Sheen
@Sheen: That doesn't make sense. You still need a place to put the `typedef` between the `foo` and base class list.
GMan
@Sheen: the same problem: where are you going to put this code? Under a separate `template<...>` it won't work, because C++ accepts only template classes/structs and functions/methods, but (pretty inconsistently) not typedefs.
Vlad
My fault, didn't read carefully.
Sheen
+3  A: 

Split it up (like it should be anyway):

// put in detail namespace/file or something in real code
template<class T, class T2>
struct foo_base
{
    typedef foo<T, T2> foo_type;
    typedef typename std::iterator_traits<T>::iterator_category category_type;

    static const bool random_access = std::is_same<category_type,
                                        std::random_access_iterator_tag>::value;
    typedef typename std::conditional<random_access,
                                        std::bidirectional_iterator_tag,
                                        category_type>::type tag_type;

    typedef bar<foo_type, tag_type>::type base_type;
}

template<class T, class T2>
struct foo :
   foo_base<T, T2>::base_type
{};

Even if there was no repeated bit, you should still split it up to keep the base type logic separate from actually inheriting the base type.

GMan
Thank you. It seems so obvious in retrospect.
Jon
@Jon: Luckily you only have to learn it once. :)
GMan