自然数n的形式定义(在集合论中)如下:
我认为这会使一些C ++代码更简单,如果我被允许这样做:
for (int n : 10)
cout << n << endl;
并打印0到9之间的数字。
所以我尝试执行以下操作,但不编译:
#include <iostream>
#include <boost/iterator/counting_iterator.hpp>
boost::counting_iterator<int> begin(int t)
{
return boost::counting_iterator<int>(0);
}
boost::counting_iterator<int> end(int t)
{
return boost::counting_iterator<int>(t);
}
int main()
{
for (int t : 10)
std::cout << t << std::endl;
return 0;
}
有关如何实现这一目标的任何建议?我用clang ++得到以下错误:
main.cpp:22:20: error: invalid range expression of type 'int'; no viable 'begin' function available
for (int t : 10)
^ ~~
但我想我应该被允许这样做! :)
编辑:我知道如果我在for循环中添加“range”(或其他一些单词),我可以“伪造”它,但我想知道是否可以这样做不
答案 0 :(得分:10)
无法做到。从draft of the C++ 14 standard的6.5.4节(但C ++ 11将非常相似)
begin-expr 和 end-expr 的确定如下:
(1.1) - 如果_
RangeT
是数组类型,[...];
嗯,这个显然不适用。 int
不是数组
(1.2) - 如果_RangeT是类类型,[...]
不,这也不适用。
(1.3) - 否则, begin-expr 和 end-expr 分别为
begin(__range)
和end(__range)
乌!这看起来很有希望。您可能需要将begin
和end
移动到全局命名空间中,但仍然......
其中
begin
在关联的命名空间中查找end
(3.4.2)。 [注意:普通不合格查询(3.4.1) 没有执行。 - 尾注]
(强调我的)。烦!没有与int
关联的任何名称空间。具体来说,请参见第3.4.2节
- 如果我们的T [
int
]是基本类型,则其关联的命名空间和类集都是空的。
唯一的工作是编写一个具有合适的begin和end方法的类range
。然后你可以写出非常pythonic:
for (int i : range(5))
答案 1 :(得分:1)
如果您查看the cppreference page for range-based for
loops,或者更好的标准相关部分([stmt.ranged]p1),您会看到它如何确定要使用的 begin_expr
为循环。 int
的相关内容是
(1.3)否则, begin-expr 和 end-expr 分别为
begin(__range)
和end(__range)
,其中start和end在相关的命名空间([basic.lookup.argdep])中查找。 [注意:不执行普通的非限定查找([basic.lookup.unqual])。 - 结束记录]
(强调添加)
不幸的是,对于用例,对于基本类型,例如int
,依赖于参数的查找永远不会返回任何内容。
相反,您可以做的是声明一个类作为范围表达式,并为其提供begin
和end
方法:
struct Range {
using value_type = unsigned int;
using iterator = boost::counting_iterator<value_type>;
unsigned int max;
iterator begin() const
{
return iterator(0);
}
iterator end() const
{
return iterator(max);
}
};
此课程的潜在改进包括:
begin
和end
方法constexpr
(这需要编写您自己的boost::counting_iterator
版本,或者让Boost制作他们的版本constexpr
)< / LI>
Range operator""_range
unsigned int
以外的其他类型。答案 2 :(得分:0)
只是为了好玩......
您已将此问题标记为C ++ 14,因此您可以使用std::integer_sequence
和std::make_integer_sequence
。
如果自然数是已知编译时间(在示例中为10
),则可以编写一个简单的constexpr
函数getArray()
(带辅助函数getArrayH
)从{0到std::array
N-1
个值
template <typename T, T ... Vals>
constexpr std::array<T, sizeof...(Vals)>
getArrayH (std::integer_sequence<T, Vals...> const &)
{ return { { Vals... } }; }
template <typename T, T Val>
constexpr auto getArray ()
{ return getArrayH(std::make_integer_sequence<T, Val>{}); }
并将其命名为
for ( auto const & i : getArray<int, 10>() )
以下是一个完整的工作示例
#include <array>
#include <utility>
#include <iostream>
template <typename T, T ... Vals>
constexpr std::array<T, sizeof...(Vals)>
getArrayH (std::integer_sequence<T, Vals...> const &)
{ return { { Vals... } }; }
template <typename T, T Val>
constexpr auto getArray ()
{ return getArrayH(std::make_integer_sequence<T, Val>{}); }
int main ()
{
for ( auto const & i : getArray<int, 10>() )
std::cout << i << std::endl;
}
答案 3 :(得分:-1)
您可以使用一些接近您想要的语法,但是您需要一个数组,其中包含您想要迭代的数字。
int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int n : a)
std::cout << n << std::endl;
http://en.cppreference.com/w/cpp/language/range-for
修改:要创建数组而不声明每个值,您可以检查此问题:Is there a compact equivalent to Python range() in C++/STL