Получите контейнерный тип из (его) типа итератора в C++ (STL)

Легко, учитывая контейнер получить связанные итераторы, пример:

std::vector<double>::iterator i; //An iterator to a std::vector<double>

Я задавался вопросом, возможно ли, учитывая тип итератора, вывести тип "соответствующего контейнера" (здесь, я предполагаю, что для каждого контейнера существует один и только один (неконстанта) итератор).

Более точно я хотел бы шаблонную метафункцию, которая работает со всеми контейнерами STL (не имея необходимость специализировать его вручную для каждого единственного контейнера) таким образом что, например:

ContainerOf< std::vector<double>::iterator >::type 

оценивает к

std::vector<double>

Действительно ли это возможно? В противном случае, почему?

Заранее спасибо за любую справку!

19
задан StephQ 10 June 2010 в 17:53
поделиться

4 ответа

Я не думаю, что это было бы возможно. В некоторых библиотеках STL у вас фактически есть векторный итератор в качестве типа указателя, , т.е. std::vector::Итератор - это T*, поэтому я не могу придумать никакого способа, которым вы могли бы вернуться к типу контейнера из этого.

9
ответ дан 30 November 2019 в 05:06
поделиться

Суть итераторов в том, что вы используете их для работы без необходимости знать базовый тип контейнера, например, передавая пара начало / конец и работа над этим диапазоном.

Однако, если все, что вас волнует, это тип итератора, я считаю, что вы можете использовать свойства итератора, чтобы определить, например, является ли итератор произвольным доступом. Возьмем std :: advance , в общем случае он вызывает operator ++ на итераторе n раз, но специализирован для итераторов с произвольным доступом, чтобы вместо этого использовать + =.

Кроме этого, я не знаю другого способа получить тип контейнера от итератора.

0
ответ дан 30 November 2019 в 05:06
поделиться

Ради забавы, вот кое-что, что я быстро взломал с помощью Boost.MPL (предупреждение: это было очень поверхностно протестировано, поэтому обращайтесь с осторожностью):

#include <boost/mpl/list.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/type_traits.hpp>
#include <vector>
#include <string>
#include <list>
#include <set>

// List of candidate container types
template<typename T>
struct ContainersOf : boost::mpl::list<
    std::vector<T>,
    std::basic_string<T>,
    std::list<T>,
    std::set<T>
>{};

// Metafunction to evaluate if IteratorT == ContainerT::iterator
template<class IteratorT, class ContainerT>
struct IsIteratorOf
{
    typedef typename 
    boost::is_same<
        IteratorT, 
        typename ContainerT::iterator
    >::type type;
};

// Metafunction to compute a container type from an iterator type
template<class IteratorT>
struct ContainerOf
{
    typedef typename 
    boost::mpl::deref<typename 
        boost::mpl::find_if<
            ContainersOf<typename std::iterator_traits<IteratorT>::value_type>,
            IsIteratorOf<IteratorT, boost::mpl::_1>
        >::type
    >::type type;
};

// Test
int main()
{
    ContainerOf<std::list<int>::iterator>::type l;
    std::list<int> l2 = l;  // OK
    std::vector<int> v = l; // Fails to compile

    return 0;
}
6
ответ дан 30 November 2019 в 05:06
поделиться

Точные типы времени выполнения итераторов C ++ STL намеренно не определены и, следовательно, зависят от реализации. Вы можете выполнить поиск в файлах заголовков поставщика вашего компилятора, чтобы узнать, какой тип фактически используется, и вывести контейнер из него, но он зависит от поставщика и версии, поэтому подвержен поломкам.

0
ответ дан 30 November 2019 в 05:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: