【问题标题】:Detecting type of data in c++ array检测c ++数组中的数据类型
【发布时间】:2016-11-18 15:18:59
【问题描述】:

这是打印出 buf 数组的 c++ 代码,其中填充了 0, 1, 2, ... 254

#include <iterator>
#include <iostream>
#include <numeric>

int main()
{
        int buf[255];

        auto it_b = std::begin(buf);
        auto it_e = std::end(buf);

        std::iota(it_b, it_e, 0);
        std::copy(it_b, it_e, std::ostream_iterator<decltype(*it_b)>(std::cout, " "));

        std::cout << std::endl;

        return 0;
}

我试图让它通用,所以只有一个地方的类型是明确的int

由于我需要明确声明 ostream_iterator 的类型,我想知道实现这一目标的最佳方法是什么。

  1. decltype(*it_b)
  2. decltype(buf[0])
  3. 其他的...

使用这种或那种方法的优点/缺点是什么?

这次假设我们被 C 风格的数组所困。

【问题讨论】:

  • std::decay_t&lt;declval(..)&gt; 避免引用。
  • using type = int;,并在之后使用type

标签: c++ arrays c++11 c++14


【解决方案1】:

为了严格正确,你应该使用std::iterator_traits

std::copy(it_b, it_e, std::ostream_iterator<
    typename std::iterator_traits<decltype(it_b)>::value_type
>(std::cout, " "));

单独decltype(*it_b) 的一个问题是它在大多数情况下会返回一个引用,这会与您正在实例化的外部模板混淆。您也可以手动删除引用:

std::copy(it_b, it_e, std::ostream_iterator<
    std::remove_reference_t<decltype(*it_b)>
>(std::cout, " "));

【讨论】:

  • 为什么不decay_t?这也将删除任何 cv 限定符,我猜这是我们不想要的。
  • @leemes 这取决于。 std::decay_t 模拟将其参数传递给函数,因此它做了很多可能相关或不相关的事情。最强大的选项仍然是iterator_traits
【解决方案2】:

可能这些都不是你想要的——在这两种情况下,你最终都会得到一个对你的类型的左值引用,在这种情况下是int&amp;。您可以通过使用std::decay 来避免它,即

std::copy(it_b, it_e, std::ostream_iterator<std::decay_t<decltype(*it_b)>>(std::cout, " "));

最简单的做法是保持类型别名并使用该别名:

using type = int;
type buf[255];

auto it_b = std::begin(buf);
auto it_e = std::end(buf);

std::iota(it_b, it_e, 0);
std::copy(it_b, it_e, std::ostream_iterator<type>(std::cout, " "));

std::cout << std::endl;

这也适用于像 vector&lt;bool&gt; 这样的病态容器,其中推断类型可能会导致令人惊讶的(和未定义的)行为。

【讨论】:

  • vector&lt;bool&gt; 是一个容器吗? ;)
  • 我知道夸大事实会咬我;) 老实说,vector&lt;bool&gt;[containers] 的一部分,并且确实满足了大部分要求。
猜你喜欢
  • 2021-08-25
  • 1970-01-01
  • 1970-01-01
  • 2019-05-15
  • 2017-01-19
  • 1970-01-01
  • 1970-01-01
  • 2012-04-12
  • 1970-01-01
相关资源
最近更新 更多