从 C++ 中的迭代器类型获取容器类型(标准格式)

发布于 2024-09-04 23:41:47 字数 459 浏览 2 评论 0原文

给定一个容器来获取关联的迭代器很容易,例如:

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

我想知道给定一个迭代器类型是否可以推断出“相应容器”的类型(这里我假设每个容器都有一个和只有一个(非常量)迭代器)。

更准确地说,我想要一个适用于所有 STL 容器的模板元函数(无需为每个容器手动专门化),例如:

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

计算结果

std::vector<double>

是否可能? 如果没有,为什么?

预先感谢您的帮助!

It is easy given a container to get the associated iterators, example:

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

I was wondering if it is possible, given an iterator type, to deduce the type of the "corresponding container" (here I am assuming that for each container there is one and only one (non-const) iterator).

More precisely, I would like a template metafunction that works with all STL containers (without having to specialize it manually for each single container) such that, for example:

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

evaluates to

std::vector<double>

Is it possible?
If not, why?

Thank you in advance for any help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

说好的呢 2024-09-11 23:41:47

我认为这是不可能的。在某些STL库上,您实际上有一个向量迭代器作为指针类型,即std::vector::iterator是一个T*,所以我想不出任何可以返回的方法到容器类型。

I don't think this would be possible. On some STL libraries you actually have a vector iterator as a pointer type, i.e. std::vector<T>::iterator is a T* so I can't think of any way you could get back to the container type from that.

金兰素衣 2024-09-11 23:41:47

只是为了好玩,我用 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;
}

Just for fun, here's something I quickly hacked with Boost.MPL (warning: This was veeeery superficially tested, so handle with care):

#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;
}
怎樣才叫好 2024-09-11 23:41:47

C++ STL 迭代器的确切运行时类型故意未定义,因此是特定于实现的。您可以搜索编译器供应商的头文件,以找出实际使用的类型,并从中推断出容器,但它是特定于供应商和版本的,因此容易损坏。

The exact runtime types of C++ STL iterators are intentionally undefined and therefore implementation-specific. You can search through your compiler vendor's header files to find out what type is actually used and deduce the container from that, but it's vendor- and version-specific, therefore prone to breaking.

玩世 2024-09-11 23:41:47

迭代器的要点是,您可以使用它们来完成工作,而无需知道底层容器类型,例如传递开始/结束对并在该范围内完成工作。

但是,如果您关心的只是迭代器类型,我相信您可以使用迭代器特征来确定迭代器是否是随机访问等。以std::advance为例,一般情况是它在迭代器上调用operator++n次,但专门针对随机访问迭代器使用+=代替。

除此之外,我不知道有什么方法可以从迭代器获取容器类型。

The point of iterators is that you use them to do work without having to know the underlying container type, for example passing a begin/end pair and doing work on that range.

However, if all you care about is the iterator type, I believe you can use iterator traits to determine for example if an iterator is random access. Take std::advance, the general case is that it calls operator++ on the iterator n times, but is specialized for random access iterators to use += instead.

Other than that I'm not aware of any way to get the container type from the iterator.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文