据我所知,基于范围的for循环只能采用c风格的数组,类型的对象具有定义的成员函数begin()
和end()
,或者是一个Type
类型,可以使用ADL找到自由函数begin(Type)
和end(Type)
。
有没有办法让循环采用类型参数,所以像这样的代码编译?
class StaticVec{
//shortened implementation
static myIterator begin();
static myIterator end();
};
void foo() {
for(auto elem : StaticVec){
dosomething(elem);
}
}
我想省略在循环中编写StaticVec::values()
的必要性。
答案 0 :(得分:6)
作为一般解决方案,您可以定义
template< class Type > struct Static_collection {};
template< class Type >
auto begin( Static_collection<Type> const& )
-> decltype( Type::begin() )
{ return Type::begin(); }
template< class Type >
auto end( Static_collection<Type> const& )
-> decltype( Type::end() )
{ return Type::end(); }
然后你可以写例如。
auto main() -> int
{
for( auto elem : Static_collection<Static_vec>() )
{
std::cout << elem << ' ';
}
std::cout << '\n';
}
<强>附录:强>
在大多数实际情况下,只需创建一个包含静态begin
和end
成员函数的类的实例就足够了,如Jarod42和Matt McNabb的答案所示(前者在我发布时已经发布了以上),例如
for( auto const& elem : StaticVec() )
{
// ...
}
如果实例创建可能会产生不良副作用,现在或可能在未来维护工作之后,请使用常规解决方案。
否则,如果实例创建基本上是免费的,我会去那。
答案 1 :(得分:4)
您仍然可以(如果适用)构造一个虚拟对象:
for (auto&& elem : StaticVec{}) {
// ...
}
答案 2 :(得分:3)
绝对不可能。示例中的范围变量是StaticVec
(它不是变量),因此它扩展到的代码将涉及auto it = StaticVec.begin()
或auto it = begin(StaticVec)
,并且这些表达式都不是有效的,函数调用要求对象不是类型。
答案 3 :(得分:1)
这是有效的,因为仍然可以通过.
表示法调用静态成员函数:
#include <iostream>
using namespace std;
struct StaticVec
{
typedef int *myIterator;
static int x[5];
static myIterator begin() { return x; }
static myIterator end() { return x + 5; }
};
int StaticVec::x[5] = { 10, 20, 30, 40, 50 };
void dosomething(int i)
{
cout << i << endl;
}
int main()
{
for(auto elem : StaticVec())
{
dosomething(elem);
}
}