【问题标题】:Obtain container type from (its) iterator type in C++ (STL)从 C++ (STL) 中的(它的)迭代器类型获取容器类型
【发布时间】:2011-03-02 07:36:08
【问题描述】:

给定一个容器很容易获得相关的迭代器,例如:

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

我想知道在给定迭代器类型的情况下是否有可能推断出“相应容器”的类型(这里我假设每个容器只有一个(非 const)迭代器)。

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

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

计算为

std::vector<double>

有可能吗? 如果不是,为什么?

提前感谢您的帮助!

【问题讨论】:

  • 您想了解迭代器的概念吗?即如果它是随机访问? STL 为此使用标签。通常没有理由知道迭代器来自哪里。
  • 您是否事先知道您是否在 7 个 STL 容器之一中拥有迭代器,或者您是否还需要一个“else”子句?

标签: c++ templates stl metaprogramming


【解决方案1】:

我认为这是不可能的。在某些 STL 库中,您实际上有一个向量迭代器作为指针类型,i.e. std::vector&lt;T&gt;::iterator is a T*,所以我想不出任何方法可以从中返回容器类型。

【讨论】:

  • 但是,它不能是任何其他 STL 容器的迭代器。只有 7 个,您可以将它们全部计算出来。
  • 这是一个公平的观点。地图和多地图之间的区别如何?你能把它们和比较运算符区分开来吗?
  • 如果结构 std::iterator_traits&lt;T&gt; 具有 typedef T container_type; 则可能是可能的,但是您可以使用此类 typedef 创建自己的 std::iterator_traits_pro
  • @MSalters 由于Allocator 参数,有无限的标准容器。我希望迭代器无法区分。
【解决方案2】:

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

【讨论】:

  • 非常感谢您的回复,但是您的解决方案需要对容器类型进行“专业化”,请参阅 ContainerOf。
【解决方案3】:

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

【讨论】:

  • 感谢您的回复!我现在意识到我的问题是故意无法“解决”的。
【解决方案4】:

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

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

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2013-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-25
  • 1970-01-01
  • 1970-01-01
  • 2015-06-06
相关资源
最近更新 更多