【问题标题】:How to retrieve value type from iterator in C++?如何从 C++ 中的迭代器中检索值类型?
【发布时间】:2011-04-27 10:46:27
【问题描述】:

对于任何熟悉 C++ 语法的人来说,我的问题肯定是一个简单的问题。我正在学习 C++,这是一些 家庭作业。

template<typename Iter>
void quickSort(Iter begin, Iter end)
{        
    //..
    auto pivot = * ( begin + (end - begin)/2 );
    //..
}

pivot 应该包含来自区间中心的值[begin, end]

我在那里编写的代码有效,但 auto 是新 C++11 语言标准中的关键字。老办法怎么办?我写什么而不是auto

【问题讨论】:

  • 这就是我喜欢看到的。刚刚学习 C++,使用迭代器和 auto 的人。 :)

标签: c++ iterator


【解决方案1】:

typename std::iterator_traits&lt;Iter&gt;::value_type

如果您的模板使用Iter 作为指针类型进行实例化,这将起作用。

顺便说一句,typename 不是类型本身的一部分。它告诉编译器value_type 确实是一种类型。如果它是函数的名称或静态数据成员,则会影响语法。编译器不一定知道它是什么,因为在编译模板时可能看不到 iterator_traitsIter 的特化。

【讨论】:

  • 这是最好的解决方案,但值得指出的是,它不是一个通用的解决方案。不能保证可以处理用户可能尝试作为迭代器传入的所有内容......他们可能仍需要将 value_type 添加到其迭代器对象(或为特征创建专门化)。另一种选择是继续使用迭代器,并为枢轴创建一个迭代器,根据需要取消引用它,而不需要模板化函数中的值类型。
  • @Tony:没错,因此auto 更好。但是,所有标准算法都要求用户传递具有iterator_traits (24.3.1) 的内容,并且用户定义的函数模板具有相同的限制是合理的。编写迭代器的人可以使用std::iterator 作为基类来弥合尝试 传入迭代器和实际传入Iterator 之间的差距;-)
  • @Tony, @Steve - 这是一个菜鸟问题,可以使用 typeid() 运算符吗?像 type_info& ti = typeid(Iter);
  • @Les:你可以使用typeid,并且应用于*Iter(而不是Iter)的typeid可以告诉你值类型的文本名称,但是你不能基于创建该类型的对象typeid ... typeid 信息中没有指向工厂方法/构造函数的链接。
  • @Les:托尼说的。 GCC 有一个typeof 扩展,C++0x 有decltype,它实际上给了你类型,而不仅仅是类型的 type_info。但在这种特殊情况下,它们都没有改进auto
【解决方案2】:

这也适用于从 c++ 11 开始:

typename Iter::value_type

所以你不必输入整个std::iterator_traits 东西。

【讨论】:

    【解决方案3】:

    史蒂夫的回答是对的;在 C++98 中,你必须使用 std::iterator_traits 或者你可以使用 Iter::value_type 如果你知道迭代器有这个 typedef(例如,从 std::iterator 派生)。 但是,您的代码中还有另一个问题:您通常不能简单地划分迭代器。当然,这适用于指针,但不适用于更一般的情况。更通用的方法是:

    Iter itPivot = std::advance(begin, std::distance(begin, end)/2);
    

    【讨论】:

    • 原始代码没有划分迭代器,这行不通,即使使用指针也不行。代码改为使用减法,它适用于所有随机访问迭代器(不仅是指针)。而且由于无论如何都会对其他迭代器类型进行快速排序(无论如何都是一种有效的实现),所以在这里使用operator - 很好。
    【解决方案4】:

    从 C++20 开始,您还可以使用以下内容(连同示例):

    #include <iostream>
    #include <vector>
    
    template<typename Iter>
    void quickSort(Iter begin, Iter end)
    {
        using T = std::remove_reference_t<std::iter_reference_t<Iter>>;
        //..
        T pivot = * ( begin + (end - begin)/2 );
        std::cout << "Element: " << pivot << std::endl;
        //..
    }
    
    int main(int argc, char* argv[]){
      std::vector<int> vec = {0,1,2,3,4,5};
      quickSort<std::vector<int>::iterator>(vec.begin(), vec.end());
      return 0;
    }
    

    输出:

    Element: 3
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-26
      • 2011-03-02
      • 2014-03-21
      • 1970-01-01
      • 2015-03-22
      • 2017-03-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多