gpt4 book ai didi

c++ - For循环索引类型推导最佳实践

转载 作者:可可西里 更新时间:2023-11-01 16:17:53 25 4
gpt4 key购买 nike

比方说,我有一个容器 c 类型,它提供了一个 size() 方法,我想遍历这个容器,同时跟踪每个项目的索引:

for (/*TODO*/ i = 0; i < c.size(); i++) {...}

在后 C++11 时代,自动类型推导可以很好地解决许多问题。我们应该用什么来代替上面的 TODO?无论 size() 的类型是什么,对我来说唯一正确的是:

for (decltype(c.size()) i = 0; i < c.size(); i++) {...}

但这似乎过于冗长,而且在我看来,不利于可读性。

另一种解决方案可能是这样的:

for (auto end = c.size(), i = 0; i < end; i++) {...}

但这也无助于提高可读性,当然,与原始片段的语义也不相同。

所以,我的问题是:在仅给定索引限制的类型的情况下,推断循环索引变量类型的最佳方法是什么。

最佳答案

对文本中第一个问题的简短回答:您应该将 /*TODO*/ 替换为 unsigned, std::size_t 或类似的东西,意思是:不必推导类型,只需选择适合任何合理容器大小的类型即可。

这将是一个无符号的、相当大的类型,因此编译器不会因为可能的精度损失而对您大喊大叫。在上面的评论中,您写道 size_t 不是 保证decltype(c.size()) 的良好替代品,但是虽然它实现一个索引与 size_t 不兼容的容器并非不可能,这样的索引肯定不是数字(因此与 i = 0 不兼容),并且容器也不会有 size 方法。 size() 方法意味着一个非负积分,并且由于 size_t 是为精确的这些数字而设计的,因此几乎不可能有一个大小不能为以它为代表。

你的第二个问题是关于如何推断类型的,你已经提供了最简单但不完美的答案。如果你想要一个不像 decltype 那样冗长并且不像 auto end 那样令人惊讶的解决方案,你可以为起始索引定义一个模板别名和一个生成器函数在一些实用程序标题中:

template <class T> 
using index_t = decltype(std::declval<T>().size());

template <class T, class U>
constexpr index_t<T> index(T&&, U u) { return u; }

//and then in the actual location of the loop:
for (auto i = index(c,0); i < c.size(); ++i) {...}
//which is the same as
for (auto i = index_t<std::vector<int>>(0); i < c.size(); ++i) {...}

如果你想要一个更通用的索引类型,例如对于没有 size 方法的数组和类,它会变得有点复杂,因为模板别名可能不是专门的:

template <class T>
struct index_type {
using type = decltype(std::declval<T>().size());
};

template <class T>
using index_t = typename index_type<T>::type;

template <class T, class U>
constexpr index_t<T> index(T&&, U u) { return u; }

//index_type specializations
template <class U, std::size_t N>
struct index_type<U[N]> {
using type = decltype(N);
};

template <>
struct index_type<System::AnsiString::AnsiString> { //YUCK! VCL!
using type = int;
};

但是,这只是针对您实际需要索引且简单的 foreach 循环不够用的少数情况的大量内容。

关于c++ - For循环索引类型推导最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26135284/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com