【问题标题】:How to declare the value of an iterator through decltype如何通过decltype声明一个迭代器的值
【发布时间】:2013-03-11 18:04:19
【问题描述】:

在 C++98 中,我通常使用以下语句在迭代器的值类型中声明变量:

typename std::iterator_traits<Iterator>::value_type value;

在 C++11 中,我们有 decltype,我认为推断值类型的最简单方法是:

decltype(*iterator) value;

不幸的是,对于大多数迭代器来说,*iterator 的类型是 value_type& 而不是 value_type。任何想法,没有类型修改类,如何将上述内容按摩成产生 value_type (而不是任何参考)?


我不认为这个问题是不合理的,因为以下内容相当健壮但最终会创建另一个变量。

auto x = *iterator;
decltype(x) value;

还要注意,我真的想要 推断类型 而不仅仅是 instance 例如如果我想声明这些值的 std::vector。

【问题讨论】:

  • 表达式*iterator的类型是std::iterator_traits&lt;Iterator&gt;::reference,而不是value_type。这不一定是value_type&amp;,并且decltype 可能会根据其值类别报告与实际不同的表达式类型。
  • 如果您只是想合并您的编辑的两行,则相当于typename std::decay&lt;decltype(*iterator)&gt;::type value;,但请查看下面的答案,不要这样做: ) 我只是将其添加为 std::decay 之前未在此 Q/A 中提及。

标签: c++ c++11 iterator typetraits decltype


【解决方案1】:

对于这个用例,我喜欢 std::decay。通常我会使用

std::vector< int > vec;
using value_type = typename std::decay< decltype(*begin(vec)) >::type; 
static_assert(std::is_same< int, value_type >::value, "expected int");

【讨论】:

  • 感谢您的建议,它确实有效(而且我学到了一些新东西!)但是当我已经拥有 Iterator 的类型时,它并不比 std::iterator_traits&lt;Iterator&gt;::value_type 更冗长。
  • 真的。 iterator_traits 是要走的路。例如,当我有一个未知的容器类型时,我实际上会更多地使用我的建议。如果你已经有了迭代器类型,那你肯定是对的。
  • 我应该注意,当迭代器的引用类型是某种不正当的代理时,这个表达式可能不起作用,就像上面提到的std::vector&lt;bool&gt; 特化一样。
【解决方案2】:

继续使用iterator_traitsdecltype(*iterator) 甚至可能是某种奇怪的代理类,以便在表达式 *iter = something 中执行特殊操作。

例子:

#include <iostream>
#include <iterator>
#include <typeinfo>
#include <vector>

template <typename T>
void print_type()
{
    std::cout << typeid(T).name() << std::endl;
}

template <typename Iterator>
void test(Iterator iter)
{
    typedef typename
        std::iterator_traits<Iterator>::value_type iter_traits_value;

    auto x = *iter;
    typedef decltype(x) custom_value;

    print_type<iter_traits_value>();
    print_type<custom_value>();
}

int main()
{
    std::vector<int> a;
    std::vector<bool> b;

    test(a.begin());
    test(b.begin());
}

MSVC 2012 上的输出:

int
int
bool
class std::_Vb_reference&lt;struct std::_Wrap_alloc&lt;class std::allocator&lt;unsigned int&gt;&gt;&gt;

它们不一样。

【讨论】:

  • 但正如我在编辑中提到的,以下工作: auto x = *iterator; decltype(x) 值;
  • @GlenLow:你还没有定义“作品”。请参阅我对答案的编辑(aschepler,请随意编辑)。
  • 啊...抱歉@GManNickG 和 aschepler,你们都是对的,我给定的表达式不一定产生与 iterator_traits 表达式相同的类型。我在想也许在 decltype() 中强制进行左值到右值的转换会使其与 iterator_traits 表达式的工作方式相同,但是对于我来说,我无法弄清楚这个表达式。
  • std::iterator_traits 专门用于某些类型的迭代器:没有与它匹配的简单表达式,也没有可以匹配在其他人添加专门化后它将执行的操作的简单表达式(不不要归结为只使用std::iterator_traits)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-03
  • 2011-06-30
  • 2018-12-09
  • 1970-01-01
相关资源
最近更新 更多